home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / mxlibs / vatpm051 / sound.c < prev    next >
C/C++ Source or Header  |  1995-04-30  |  111KB  |  3,122 lines

  1. /**************************************************************************
  2.                         VARMINT'S AUDIO TOOLS
  3.  
  4.   Source code: SOUND.C
  5.  
  6.                Turbo C++ V 3.1
  7.  
  8.                Be careful about the memory model!  The definition for
  9.            SAMPLE will define what model you should use.
  10.  
  11.                Turn off stack checking and stack warning options in your
  12.                compiler.
  13.  
  14.   Written by: Eric Jorgensen (April, 1995)
  15.               smeagol@rt66.com
  16.  
  17.           Adapted from original Source by Peter Sprenger
  18.  
  19.   sound.c is an adaptation (by Eric Jorgensen) from Peter Sprenger's
  20.   SoundX library.  Eric's modifications (In part) are as follows:
  21.  
  22.     - Removal of all VOC, PLAY, and MIXER functions
  23.     - reprogramming of DMA functions
  24.     - Addition of MIDI functions
  25.     - Addition of an interrupt driven sound handler
  26.     - Addition of numerous comments (about 98% of all comments are Eric's)
  27.     - Consolidation of all functions into a single file
  28.     - Rewriting of some of Peter's original functions to improve
  29.       readability and performance.
  30.     - Addition of MOD functions
  31.     - MPU-401 output and setup
  32.     - Removal of inline asembly functions
  33.     - CLeanup of Sound Blaster Autoinitialization code
  34.  
  35.   As of  April 19, about the only code left that is Peter's is some of the
  36.   Auto initialization code and some of the FM functions.
  37.  
  38. ----------------------------------------------------------------------
  39.  Peter Sprenger's Original Copywrite is as follows:
  40.  
  41.  
  42.  * Copyright 1993 by Peter Sprenger   Pete@amber.dinoco.de
  43.  *                   5014 Kerpen 3
  44.  *                   Germany
  45.  *
  46.  * Permission to use, copy, modify, and distribute this
  47.  * software and its documentation for any purpose and without
  48.  * fee is hereby granted, provided that the above copyright
  49.  * notice appear in all copies.  The author Peter Sprenger
  50.  * makes no representations about the suitability of this
  51.  * software for any purpose.  It is provided "as is" without
  52.  * express or implied warranty.
  53. ----------------------------------------------------------------------
  54.  
  55.  In the spirit of Peter's effort, I am offering my modification of his
  56.  library as FREEWARE.  You are free to use it and distribute this
  57.  library, but you may charge no fee for it.  If you construct another
  58.  sound library based on this one, it must be freeware, too.  This
  59.  restriction does not apply to programs that only use this library to
  60.  generate audio output.  (ie:  if you make a game that uses this
  61.  library for sound generation, you can charge all the money
  62.  you want for your game.)
  63.  
  64.                            **** WARNING ****
  65.  
  66.  Use Varmint's Audio tools at your own risk.  This code has only been lightly
  67.  tested and has been found to cause cancer in laboratory rats.
  68.  
  69.  
  70.  
  71.  
  72. **************************************************************************/
  73.  
  74.  
  75.  
  76. #include "sound.h"
  77. #include "dos.h"
  78.  
  79. #define CINTNO 0
  80. #define SLAVEPIC 2
  81. #define RTCINTNO 8
  82. #define WORD unsigned short
  83. #define BYTE unsigned char
  84. #define TD midi_data->track[i] + trkloc[i]
  85. #define DOWN_SEMITONE     1.059463
  86. #define UP_SEMITONE       0.943874
  87. #define DOSYNC  if(sync_on && inp(0x3da)&0x08) vsyncclock = 1000
  88. #define DMAAUTOINIT 0x58
  89. #define DMAONESHOT 0x48
  90.  
  91.  
  92. //-------------------------------- Internal Function prototypes
  93.  
  94. void MPU_Write(BYTE b);
  95. void interrupt _saveregs sb_int(void);
  96. static cardtype CheckHard(void);
  97. static short test_int(void);
  98. static short scan_int(void);
  99. static short FM_Detect(void);
  100. BYTE FM_Status(void);
  101. short DSP_Reset(void);
  102. BYTE DSP_Read(void);
  103. void DSP_Write(BYTE output);
  104. WORD DSP_GetVersion(void);
  105. void SB_SetVect(void);
  106. void SB_RemoveVect(void);
  107. short get_sb_env(void);
  108. short CardCheck(void);
  109. cardtype WhichCard(void);
  110. BYTE int2vect(BYTE intnr);
  111. void enable_int(BYTE nr);
  112. void disable_int(BYTE nr);
  113. void InitT2(void);
  114. void measure(void);
  115. void dma_set(BYTE *sound_address,WORD len,BYTE channel);
  116. WORD polldma(BYTE channel);
  117. short ReadVarLen(BYTE *data,int *value);
  118. int ReadLong(FILE *infile);
  119. short ReadShort(FILE *infile);
  120. void MidiPlayer(void);
  121. short getvoice(VOICE v[],short track,short channel, short note);
  122. void dotick(void);
  123. void dodiv(void);
  124.  
  125.  
  126. //-------------------------------- Global function pointers
  127.                                 // These are used by the interrupt routines
  128.                                 // To help keep track of interrupts that
  129.                                 // Get shuffled around.
  130.  
  131. void (interrupt *handlerint)(void) = sb_int;
  132. static void (interrupt *orgint)(void) = NULL;
  133. static void (interrupt *orgtick)(void)= NULL;
  134. static void (interrupt *orgirqint)(void) = NULL;
  135. static void (*call_func)(void);
  136.  
  137. //-------------------------------- FM variables and data
  138.  
  139. static WORD FM_off[9]={0,0x100,0x200,0x800,0x900,0xa00,0x1000,0x1100,0x1200};
  140. static BYTE FM_fnr[12]={0x57,0x6b,0x81,0x98,0xb0,0xca,0xe5,0x02,0x20,0x41,0x63,0x87};
  141. static BYTE FM_key_or[12]={1,1,1,1,1,1,1,2,2,2,2,2};
  142. static BYTE FM_key[9],FM_keyscale1[9],FM_keyscale2[9];
  143. static BYTE FM_vol[9] = {0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};
  144.  
  145. //-------------------------------- setup data and variables
  146.  
  147. static WORD ioaddr[6]={0x220,0x240,0x210,0x230,0x250,0x260};
  148. static BYTE intrx[8]={5,7,10,11,12,15,2,3};
  149. int realhandle;
  150. WORD io_addr= 0x220,intnr= 5,card_id=1,fm_addr;
  151. int dma_ch=1;
  152. WORD fm_left,fm_right,fm_both,dsp_vers;
  153. static WORD mue3,mue23,wh_card,rythm=0xbd00;
  154. static WORD dma_adr[8]= {0x00,0x02,0x04,0x06,0xc0,0xc4,0xc8,0xcc};
  155. static WORD dma_len[8]= {0x01,0x03,0x05,0x07,0xc2,0xc6,0xca,0xce};
  156. static WORD dma_page[8]={0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8a};
  157. SBERROR sberr = 0;
  158. char *errname[] = {
  159.   "Cannot detect FMchip",
  160.   "Cannot detect DSP",
  161.   "Cannot find an open IRQ",
  162.   "Cannot find an open DMA channel",
  163.   "Cannot allocate memory for DMA buffer"};
  164. volatile tst_cnt;
  165. short mpu_available = FALSE;
  166. BYTE DMA_controlbyte = DMAAUTOINIT;
  167.  
  168. //-------------------------------- DMA/DSP mixer varaibles and data
  169.  
  170. WORD dma_bufferlen = 60;
  171. BYTE *dma_buffer = NULL;
  172. BYTE *playahead_buffer = NULL;
  173. short *mix_buffer = NULL;
  174. short sounds_in_queue = 0;
  175. short sample_rate = 11000;
  176. SAMPLE *sounddata[MAXSOUNDS];
  177. DWORD soundpos[MAXSOUNDS];
  178.  
  179. //-------------------------------- Timer varaibles
  180.  
  181. static WORD timer_val,timer_hold,timer_diff,mue999;
  182. static WORD timadd,timsum;
  183.  
  184. //-------------------------------- MOD varaibles
  185.  
  186. MOD *mod_data = NULL;
  187. short mod_on = FALSE,mod_reset = FALSE,mod_tablepos=0;
  188. BYTE *mod_pattern,*mod_pstop,*mod_loopspot=NULL;
  189. short mod_loopcount = -1;
  190. short mod_bytespertick = 220,mod_ticksperdivision = 6;
  191. short mod_currentbyte = 0,mod_currenttick = 0;
  192. short mod_divoffset =0;
  193. short mod_glissando = FALSE;
  194. short mod_finetune = 0;
  195. short mod_patterndelay = 0;
  196. short mod_volume = 7;
  197. BYTE channel_select[4] = {1,1,1,1};
  198.  
  199. CHANNEL chan[4];
  200.  
  201.  
  202.  
  203. //-------------------------------- MIDI/MPU varaibles
  204.  
  205. MIDI *midi_data = NULL;
  206. short midi_reset = TRUE;
  207. short midi_on = FALSE;
  208. short midi_mpuout = FALSE;
  209. short midi_fmout = TRUE;
  210. short midi_dumbmode = TRUE;
  211. short mpu_timeout;
  212. WORD midi_port = 0x330;
  213. float midi_callfreq = 1.0;
  214. float midi_usertempo = 2.0;
  215. float midi_tempoadjust = 2.0;
  216. BYTE music_volume = 0x32;  // +ECODE change me to midi_volume
  217. DWORD vclock=0;
  218. static BYTE defaultpatchmap[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  219. BYTE *midi_patchmap;
  220.  
  221. //-------------------------------- Miscellaneous varaibles
  222.  
  223. short debugnum=0;
  224. short debug_antistatic = TRUE;
  225. short debug_intdisable = FALSE;
  226. WORD DSP_overhead = 0;
  227. extern unsigned _stklen = 16000;  // The stack is usually only 4K, but
  228.                                   // I was getting stack overflow problems
  229.                                   // with that ammount.
  230. WORD vsync_toolong = 10;          // This is the number of vclock ticks that
  231.                                   // tells us we have waited to long in
  232.                                   // the VarmintVSync() function.
  233. WORD vsyncclock = 0;
  234. BYTE sync_on = FALSE;
  235.  
  236.  
  237.  
  238.  
  239.  
  240. /**************************************************************************
  241.   void Go_Varmint(void)
  242.   void Dropdead_Varmint(void)
  243.  
  244.   DESCRIPTION:  Starts/stops the interrupt routine for Varmint's audio tools
  245.  
  246. **************************************************************************/
  247. void Go_Varmint(void)
  248. {
  249.   SB_SetVect();                         // Install the sound kernel
  250.  
  251.   if(card_id > 2) {                     // SB2.0 or better?
  252.     DSP_Write(0x48);                     // Set DSP for 8bit Autoinit DMA
  253.     DSP_Write((dma_bufferlen) & 0xff);  // Write length low byte
  254.     DSP_Write((dma_bufferlen) >> 8);    // Write length high byte
  255.  
  256.     dma_set(dma_buffer,dma_bufferlen,dma_ch);
  257.     DSP_Write(0x1C);                     // Set DSP for Autoinit 8bit DMA
  258.   }
  259.   else {                                // SB 1.x?
  260.     DMA_controlbyte = DMAONESHOT;
  261.   }
  262.  
  263.   DSP_Write(DSP_INVOKE_INTR);           // Ignition!
  264. }
  265.  
  266. void Dropdead_Varmint(void)
  267. {
  268.   DSP_Write(0xD0);                      // Halt DMA
  269.   if(card_id>2) DSP_Write(0xDA);        // Halt Autoinitialized DMA
  270.   DSP_Write(0xD0);                      // Halt DMA
  271.   SB_RemoveVect();                      // Clean up sound kernel
  272.  
  273.   real_free(realhandle);  // Deallocate the memory for DMA buffer to be freed
  274.  
  275. }
  276.  
  277. /*  ---------------  FM  Stuff ------------ */
  278.  
  279.  
  280.  
  281. /**************************************************************************
  282.   void FM_Write(WORD data)
  283.  
  284.   DESCRIPTION: Writes a byte to the FM chip.  The high byte is the
  285.                register, the low byte is the data.
  286.  
  287. **************************************************************************/
  288. void FM_Write(WORD data)
  289. {
  290.   BYTE reg,value;
  291.  
  292.   reg = (data & 0xff00)>>8;       // extract register and data value
  293.   value = data & 0x00ff;
  294.  
  295.   outp(fm_addr,reg);          // Write the register
  296.   mdelay(mue3);                   // Wait three microseconds
  297.  
  298.   outp(fm_addr+1,value);      // Write the data
  299.   mdelay(mue3);                   // Wait 23 microseconds
  300. }
  301.  
  302.  
  303. /**************************************************************************
  304.   void FM_Reset()
  305.  
  306.   DESCRIPTION:  Resets the FM chip by clearing all the registers then
  307.                 setting a few appropriate bits.
  308.  
  309. **************************************************************************/
  310. void FM_Reset(void)
  311. {
  312.   WORD i;
  313.   for(i = 0; i <= 0xf500 ; i+= 0x100) FM_Write(i);
  314.   FM_Write(0x0120);                 // Turn on Wave form control
  315.   FM_Write(0xbdc0);                 // Set AM and Vibrato to high
  316. }
  317.  
  318.  
  319. /**************************************************************************
  320.   BYTE FM_Status()
  321.  
  322.   DESCRIPTION:  Reads the status byte of the FM chip
  323.  
  324. **************************************************************************/
  325. BYTE FM_Status(void)
  326. {
  327.   return (inp(fm_addr));
  328.  
  329. }
  330.  
  331.  
  332. /**************************************************************************
  333.   static short FM_Detect()
  334.  
  335.   DESCRIPTION:  Detects the presence of an FM chip
  336.  
  337. **************************************************************************/
  338. static short FM_Detect(void)
  339. {
  340.   FM_Write(0x0100); /* init Test register */
  341.  
  342.   FM_Write(0x0460); /* reset both timer */
  343.   FM_Write(0x0480); /* enable interrupts */
  344.   if(FM_Status() & 0xe0) return(FALSE);
  345.  
  346.   FM_Write(0x02ff); /* write ffh to timer 1 */
  347.   FM_Write(0x0421); /* start timer 1 */
  348.   if(fm_addr==0x388) msdelay(21); /* wait 21000 mcs */
  349.   else mdelay(mcalc(80));   /* wait at least 80 microsec */
  350.   if((FM_Status() & 0xe0)!=0xc0) return(FALSE);
  351.  
  352.   FM_Write(0x0460); /* reset both timer */
  353.   FM_Write(0x0480); /* enable interrupts */
  354.   return(TRUE);
  355. }
  356.  
  357.  
  358.  
  359. /**************************************************************************
  360.   void FM_SetVoice(BYTE voice,BYTE *ins)
  361.  
  362.   DESCRIPTION: Sets the voice from an 11 byte array
  363.  
  364.     BYTE    ID
  365.  
  366.       0      Ampmod /vib /envtype /scale rate/ mod freq mult (oper 1)
  367.       1      Ampmod /vib /envtype /scale rate/ mod freq mult (oper 2)
  368.       2      Key level scaling/ total level (oper 1)
  369.       3      Key level scaling/ total level (oper 2)
  370.       4      Attack Rate/ Decay rate  (oper 1)
  371.       5      Attack Rate/ Decay rate  (oper 2)
  372.       6      Sustain Level/ Release rate (oper 1)
  373.       7      Sustain Level/ Release rate (oper 2)
  374.       8     Feedback / Algorythm (oper 1&2)
  375.       9      Wave Form  Select (oper 1)
  376.       10    Wave Form  Select (oper 2)
  377.  
  378. **************************************************************************/
  379. void FM_SetVoice(BYTE voice,BYTE *ins)
  380. {
  381.   if(voice > 8) return;
  382.  
  383.   FM_keyscale1[voice]=ins[2] & 0xc0;        // store key scaling for FM_Vol
  384.   FM_keyscale2[voice]=ins[3] & 0xc0;
  385.                                             // Write voice data
  386.   FM_Write((0x2000 + FM_off[voice]) | ins[0]);
  387.   FM_Write((0x2300 + FM_off[voice]) | ins[1]);
  388.                                             // For the next two, we want to
  389.                                             // make sure current volume is
  390.                                             // preserved.
  391.   FM_Write((0x4000 + FM_off[voice]) | (ins[2] & 0xc0) | FM_vol[voice]);
  392.   FM_Write((0x4300 + FM_off[voice]) | (ins[3] & 0xc0) | FM_vol[voice]);
  393.                                             // the rest of the voice is just
  394.                                             // straight writes.
  395.   FM_Write((0x6000 + FM_off[voice]) | ins[4]);
  396.   FM_Write((0x6300 + FM_off[voice]) | ins[5]);
  397.   FM_Write((0x8000 + FM_off[voice]) | ins[6]);
  398.   FM_Write((0x8300 + FM_off[voice]) | ins[7]);
  399.   FM_Write((0xc000 + voice * 0x100) | ins[8]);
  400.   FM_Write((0xE000 + FM_off[voice]) | ins[9]);
  401.   FM_Write((0xE300 + FM_off[voice]) | ins[10]);
  402. }
  403.  
  404.  
  405. /**************************************************************************
  406.   void FM_SetFreq(BYTE voice,short freq)
  407.  
  408.   DESCRIPTION: sets an explicit pseudo frequency (0 - 0xffff)
  409.  
  410.   Note: There is no way to really set a direct frequency on an FM
  411.         chip, so I wrote this routine which is based on octaves, so I
  412.         imagine it is slightyl non-linear.  Still, it is good for
  413.         special effects.
  414.  
  415. **************************************************************************/
  416. void FM_SetFreq(BYTE voice,WORD freq)
  417. {
  418.   BYTE highbits,lowbits;
  419.   WORD data,frac;
  420.   short octave;
  421.  
  422.   octave = (freq / 0x2000);       // Extract octtave number (0-7)
  423.                                   // convert remaining fraction into a
  424.                                   // 10 bit value.
  425.   frac = ((double)(freq - octave * 0x2000)/(double)0x2000) * 0x157 + 0x157;
  426.  
  427.   highbits = (frac & 0x300) >> 8; // divide fraction into low and high bits
  428.   lowbits = frac & 0xff;
  429.  
  430.   data=0xa000+(voice<<8)|lowbits; // store low bits for now
  431.   FM_key[voice]=highbits|(octave<<2);  // save high bits for Key_on(); (octave 4)
  432.   FM_Write(data);                 // write low bits to FM chip;
  433. }
  434.  
  435. /**************************************************************************
  436.   void FM_SetNote(BYTE voice,BYTE note)
  437.  
  438.   DESCRIPTION: sets the frequency for a chromatic note
  439.  
  440. **************************************************************************/
  441. void FM_SetNote(BYTE voice,BYTE note)
  442. {
  443.   BYTE blk,notex;
  444.   WORD data;
  445.                               //  calculate freq number and octave
  446.   notex=note-24;
  447.   blk=1;
  448.   while(notex>=12)
  449.   {
  450.     notex-=12;
  451.     blk++;                    // octave number
  452.   }
  453.   data=0xa000+(voice<<8)|FM_fnr[notex];
  454.   FM_key[voice]=FM_key_or[notex]|(blk<<2); // save part of the note for Key_on()
  455.   FM_Write(data);             // write note to the chip
  456. }
  457.  
  458.  
  459. /**************************************************************************
  460.   void FM_SetVol(BYTE voice,BYTE vol)
  461.  
  462.   DESCRIPTION: The the volume (0-63) for a voice.
  463.  
  464. **************************************************************************/
  465. void FM_SetVol(BYTE voice,BYTE vol)
  466. {
  467.   if (voice >8) return;
  468.                                // Convert  volume from a logical value to
  469.                                // the value that is really used.  ie: 3f is
  470.                                // really the quietest setting, while 0 is
  471.                                // the loudest.  Weird, eh?
  472.   FM_vol[voice] = (0x3f - (vol & 0x3f));
  473.                                // Write the volume while preserving the
  474.                                // other important parts of the voice.
  475.   FM_Write((0x4000+FM_off[voice]) |FM_vol[voice] | FM_keyscale1[voice]);
  476.   FM_Write((0x4300+FM_off[voice]) |FM_vol[voice] | FM_keyscale2[voice]);
  477.  
  478. }
  479.  
  480. /*  A NOTE ABOUT RYTHM FUNCTIONS:
  481.  
  482.   I've only played around with these functions a little bit. Here are some
  483.   things that I've learned:
  484.  
  485.     - only channels 6,7,and 8 are affected by the rythm mode.
  486.     - You will need to develop special instrument definitions to get
  487.       the rythm instruments to sound right.  The most important parameters
  488.       in a rythm instrument definition are attack/decay/sustain rates and
  489.       the waveform (bytes 9 and 10).
  490.     - channels 6,7, and 8 each behave differently in rythm mode:
  491.  
  492.         6 - Instrumental.  Sounds like a triangle
  493.         7 - White noise.  Sounds like a snare drum
  494.         8 - High white noise.  Sounds like a Cymbal.
  495.  
  496.     - If you want to add white noise effects to your program (Gun shots
  497.       engines, etc...)  channel 7 in rythm  mode is a good source.
  498.  
  499.                                       - ERIC
  500. */
  501.  
  502.  
  503.  
  504. /**************************************************************************
  505.   void FM_RythmMode(BYTE bool)
  506.  
  507.   DESCRIPTION:  Turns on/off rythm mode based on input.
  508.  
  509. **************************************************************************/
  510. void FM_RythmMode(BYTE bool)
  511. {
  512.   WORD data;
  513.  
  514.   if(bool) data=0xbde0;
  515.   else data=0xbdc0;
  516.   rythm=data;                         // This global keeps track of the
  517.                                       // mode for other rythm functions.
  518.   FM_Write(data);
  519. }
  520.  
  521.  
  522. /**************************************************************************
  523.   void FM_RythmOn(BYTE inst)
  524.  
  525.   DESCRIPTION: Turns on a Specified  rythm instrument. You should use these
  526.                 definitions:
  527.  
  528.                       FM_HIHAT
  529.                       FM_TOPCYM
  530.                       FM_TOMTOM
  531.                       FM_SNARE
  532.                       FM_BASS
  533.  
  534. **************************************************************************/
  535. void FM_RythmOn(BYTE inst)
  536. {
  537.   rythm|=inst;
  538.   FM_Write(rythm);
  539. }
  540.  
  541. /**************************************************************************
  542.   void FM_RythmOff(BYTE inst)
  543.  
  544.   DESCRIPTION: Turns off a Specified  rythm instrument. You should use these
  545.                 definitions:
  546.  
  547.                       FM_HIHAT
  548.                       FM_TOPCYM
  549.                       FM_TOMTOM
  550.                       FM_SNARE
  551.                       FM_BASS
  552.  
  553. **************************************************************************/
  554. void FM_RythmOff(BYTE inst)
  555. {
  556.   rythm&=(~inst);
  557.   FM_Write(rythm);
  558. }
  559.  
  560.  
  561. /**************************************************************************
  562.   void FM_KeyOn(BYTE voice)
  563.  
  564.   DESCRIPTION: Turn on an FM voice.
  565.  
  566.                This description is misleading, since in my experirnce,
  567.                FM voices are always on.  This function really just
  568.                triggers the FM voice.
  569.  
  570. **************************************************************************/
  571. void FM_KeyOn(BYTE voice)
  572. {
  573.   WORD data;
  574.  
  575.   if(voice > 8) return;
  576.  
  577.   data=0xb000+(voice<<8);            // set write address
  578.   data |= FM_key[voice]|0x20;        // set key on bit and frequency
  579.    FM_Write(data);
  580. }
  581.  
  582.  
  583. /**************************************************************************
  584.   void FM_KeyOff(BYTE voice)
  585.  
  586.   DESCRIPTION: Turn off an FM voice.
  587.  
  588.                 (See FMKeyOn)  Again, I've found that voices are always
  589.                 on, and to turn them off you really need to just set the
  590.                 volume to 0.  Turning off the Key_on bit may prepare
  591.                 the voice for a trigger, though.
  592.  
  593. **************************************************************************/
  594. void FM_KeyOff(BYTE voice)
  595. {
  596.   WORD data;
  597.  
  598.   if(voice > 8) return;
  599.  
  600.   data=0xb000+(voice<<8);            // set address
  601.   data |= FM_key[voice];              // preserve frequency data
  602.   FM_Write(data);
  603.                                      //  working.
  604. }
  605.  
  606.  
  607.  
  608. /*  ---------------  DSP  Stuff ------------ */
  609.  
  610.  
  611.  
  612.  
  613. /**************************************************************************
  614.   short DSP_Reset()
  615.  
  616.   DESCRIPTION: Resets the DSP
  617.  
  618. **************************************************************************/
  619. short DSP_Reset(void)
  620. {
  621.   short i;
  622.  
  623.   outp(io_addr+DSP_RESET,1);        // Write a 1 to the DSP reset port
  624.   mdelay(mue3);                          // Wait 3 microseconds
  625.   outp(io_addr+DSP_RESET,0);        // Write a 0 to the DSP reset port
  626.  
  627.  
  628.   for(i=0;i<50;i++) {                   // DSP should send back an 0xaa
  629.     mdelay(mue3);
  630.     if(DSP_Read()==0xaa) return(TRUE);
  631.   }
  632.  
  633.   return(FALSE);
  634. }
  635.  
  636.  
  637. /**************************************************************************
  638.   BYTE DSP_Read()
  639.  
  640.   DESCRIPTION:  reads a byte from the dsp
  641.  
  642.  
  643. **************************************************************************/
  644. BYTE DSP_Read(void)
  645. {
  646.                                       // Read until high bit of status port
  647.                                       // is set.
  648.   while(!(inp(io_addr+DSP_RSTATUS) &  0x80));
  649.   return (inp(io_addr+DSP_READ)); // Send back the value of the read port
  650. }
  651.  
  652.  
  653. /**************************************************************************
  654.   short MPU_Reset(void)
  655.  
  656.   DESCRIPTION:  This function resets the MPU-401 chip and reports wether
  657.                 or not it was succesful by returning a boolen.
  658.  
  659.   RETURNS:
  660.  
  661.     True if successful, False if not
  662. **************************************************************************/
  663. short MPU_Reset(void)
  664. {
  665.   short success = TRUE;
  666.  
  667.   outp(midi_port+1,0xFF);          // Send reset command
  668.  
  669.   mpu_timeout = 0;
  670.   while(mpu_timeout<1000) {            // Wait for ready bit to clear
  671.     mpu_timeout++;
  672.     if(!(inp(midi_port+1)&0x80)) break;
  673.   }
  674.  
  675.   if(mpu_timeout == 1000) {           // Did it Time out?
  676.     outp(midi_port+1,0xFF);        // Try again
  677.  
  678.     mpu_timeout = 0;
  679.     while(mpu_timeout<1000) {          // Wait for ready bit to clear
  680.       mpu_timeout++;
  681.       if(!(inp(midi_port+1)&0x80)) break;
  682.     }
  683.  
  684.     if(mpu_timeout == 1000) success = FALSE; // Two timeouts and you're out
  685.   }
  686.  
  687.   outp(midi_port+1,0x3F);          // Put MPU in Uart Mode
  688.  
  689.   mpu_timeout = 0;
  690.   while(mpu_timeout<1000) {            // Wait for ready bit to clear
  691.     mpu_timeout++;
  692.     if(!(inp(midi_port+1)&0x80)) break;
  693.   }
  694.   if(mpu_timeout == 1000) success = FALSE;   // No UART?  No MIDI.
  695.  
  696.   return(success);
  697.  
  698. }
  699. /**************************************************************************
  700.   void MPU_Write(BYTE b)
  701.  
  702.   DESCRIPTION:  Writes a byte  the midi data port
  703.  
  704. **************************************************************************/
  705. void MPU_Write(BYTE b)
  706. {
  707.   mpu_timeout = 0;
  708.  
  709.   while(mpu_timeout<1000) {        // Wait for ready bit to clear
  710.     mpu_timeout++;
  711.     if(!(inp(midi_port+1)&0x40)) break;
  712.   }
  713.  
  714.   outp(midi_port,b);           // Write the byte!
  715. }
  716.  
  717.  
  718. /**************************************************************************
  719.   void DSP_Write(BYTE output)
  720.  
  721.   DESCRIPTION: Writes a byte to the DSP
  722.  
  723. **************************************************************************/
  724. void DSP_Write(BYTE output)
  725. {
  726.                                       // Read until high bit of status port
  727.                                       // is clear.
  728.   while((inp(io_addr+DSP_WSTATUS) &  0x80));
  729.   outp(io_addr+DSP_WRITE,output); // Write our byte
  730. }
  731.  
  732.  
  733. /**************************************************************************
  734.   short get_sb_env()
  735.  
  736.   DESCRIPTION:  Get sound blaster information from the environment
  737.                 variable "BLASTER"
  738.  
  739. **************************************************************************/
  740. short get_sb_env(void)
  741. {
  742.   char *str;
  743.   short i;
  744.   short outvalue = TRUE;
  745.  
  746.   str=getenv("BLASTER");
  747.   if(!str) return(FALSE);                 // no blaster variable? go home
  748.  
  749.                       // Convert string to upper case
  750.   for(i = 0 ; i < strlen(str); i++) *(str+i) = toupper(*(str+i));
  751.                       // pick apart variable for info.
  752.                       // Io address
  753.   for(i = 0; *(str+i) != 0 && *(str + i) != 'A'; i++);
  754.   if(*(str+i)){
  755.     sscanf(str+i+1,"%hx",&io_addr);
  756.     if(io_addr<0x210 || io_addr>0x260) outvalue = FALSE;
  757.   }
  758.                       // MIDI port address
  759.   for(i = 0; *(str+i) != 0 && *(str + i) != 'P'; i++);
  760.   if(*(str+i)) sscanf(str+i+1,"%hx",&midi_port);
  761.  
  762.                       // Dma channel number
  763.   for(i = 0; *(str+i) != 0 && *(str + i) != 'D'; i++);
  764.   if(*(str+i)){
  765.     sscanf(str+i+1,"%hi",&dma_ch);
  766.     if(dma_ch > 7) outvalue = (FALSE);    // only 0-7 allowed
  767.   }
  768.  
  769.                       // IRQ interrupt number
  770.   for(i = 0; *(str+i) != 0 && *(str + i) != 'I'; i++);
  771.   if(*(str+i)){
  772.     sscanf(str+i+1,"%hd",&intnr);
  773.     if(intnr < 2  || intnr > 10) outvalue =  (FALSE);
  774.   }
  775.  
  776.                       // card_id
  777.   for(i = 0; *(str+i) != 0 && *(str + i) != 'T'; i++);
  778.   if(*(str+i)){
  779.     sscanf(str+i+1,"%hd",&card_id);
  780.     if(card_id < 1 && card_id > 6) outvalue = FALSE; // 1 = SB 1.x 6 = SB AWE
  781.   }
  782.  
  783.   return(outvalue);
  784. }
  785.  
  786.  
  787.  
  788. /**************************************************************************
  789.   WORD DSP_GetVersion()
  790.  
  791.   DESCRIPTION:  Get the version number of the DSP
  792.  
  793. **************************************************************************/
  794. WORD DSP_GetVersion(void)
  795. {
  796.   DSP_Write(DSP_GET_VERS);
  797.   return((WORD)DSP_Read()*256+DSP_Read());
  798. }
  799.  
  800.  
  801. /*  ---------------  Misc.  Stuff ------------ */
  802.  
  803.  
  804.  
  805. /**************************************************************************
  806.   short CardCheck()
  807.  
  808.   DESCRIPTION:  Check for both FM chip and DSP
  809.  
  810. **************************************************************************/
  811. short CardCheck(void)
  812. {
  813.   short ret=0;
  814.  
  815.   if(FM_Detect()) ret|=FM_DETECT;
  816.   if(DSP_Reset()) ret|=DSP_DETECT;
  817.   return(ret);
  818. }
  819.  
  820.  
  821. /**************************************************************************
  822.   static void far interrupt testn_int()
  823.  
  824.   DESCRIPTION:  This function is stored as an interrupt to test
  825.                 various interrupt vectors by test_int()
  826.  
  827. **************************************************************************/
  828. static void interrupt testn_int(void)
  829. {
  830.   tst_cnt++;                               // increment our test counter
  831.  
  832.   inp(io_addr+DSP_RSTATUS);            // Acknowledge DSP interrupt
  833.  
  834.   if(intnr < 8) outp(0x20,0x20);       // Clear PIC
  835.   else outp(0xa0,0x20);
  836. }
  837.  
  838.  
  839.  
  840. /**************************************************************************
  841.   static short test_int()
  842.  
  843.   DESCRIPTION:  This function is used by scan_int() to test interrupt
  844.                 stuff.  It installs a test interrupt in the
  845.                 requested spot (intnr) then sees if the DSP can
  846.                 use it.
  847.  
  848. **************************************************************************/
  849. static short test_int(void)
  850. {
  851.   short i;
  852.   BYTE int1,int2;
  853.  
  854.   orgint=_dos_getvect(int2vect(intnr));   // Save original interrupt
  855.  
  856.   int1 = inp(0x21);                    // Save PIC settings
  857.   int2 = inp(0xa1);
  858.  
  859.   tst_cnt=0;                               // reset our test interrupt counter.
  860.  
  861.   disable_int(intnr);                     // put in our test interrupt
  862.   _dos_setvect(int2vect(intnr),testn_int);
  863.   enable_int(intnr);
  864.  
  865.   DSP_Write(DSP_INVOKE_INTR);              // Force DSP interrupt
  866.  
  867.   for(i=0;i<30000;i++) if(tst_cnt) break; // wait for interrupt code to happen
  868.  
  869.   disable_int(intnr);                     // put original interrupt back
  870.   _dos_setvect(int2vect(intnr),orgint);
  871.  
  872.   outp(0x21,int1);                    // restore PIC settings
  873.   outp(0xa1,int2);
  874.  
  875.   if(i==30000) return(FALSE);             // Timed out? No good!
  876.   else return(TRUE);
  877. }
  878.  
  879.  
  880. /**************************************************************************
  881.   static short scan_int()
  882.  
  883.   DESCRIPTION: This makes sure that the interrupt number picked by the
  884.                 IRQ specification is a good choice.
  885.  
  886. **************************************************************************/
  887. static short scan_int(void)
  888. {
  889.   short i;
  890.  
  891.   if(test_int()) return(intnr);   // Original choice good?
  892.  
  893.   for(i=0;i<8;i++)                // Try our eight best guesses
  894.   {
  895.     intnr=intrx[i];
  896.     if(test_int()) return(i);
  897.   }
  898.   return(0);
  899. }
  900.  
  901.  
  902. /**************************************************************************
  903.   static cardtype CheckHard()
  904.  
  905.   DESCRIPTION:  Checks hardware for DSP and FM chip
  906.  
  907. **************************************************************************/
  908. static cardtype CheckHard(void)
  909. {
  910.   short ret;
  911.  
  912.   ret=DSP_Reset();
  913.   if(ret)
  914.   {
  915.     if(!scan_int()) {              // Scan IRQ's
  916.       sberr= irqerr;
  917.       return(none);
  918.     }
  919.  
  920.     fm_addr=io_addr+FM_BOTH_OFF;
  921.     if(!FM_Detect()) {
  922.       sberr = fmerr;
  923.       return(none);                 /* no fm? -> damaged! */
  924.     }
  925.  
  926.                                    // SBPro  checking here.  Not too critical
  927. /*    fm_both=fm_addr;
  928.     fm_addr=io_addr+FM_RIGHT_OFF;
  929.     fm_right=fm_addr;
  930.     ret3=FM_Detect();
  931.     fm_addr=fm_both;
  932.  
  933.     if(ret3)
  934.     {
  935.       wh_card=sbpro;
  936.       fm_left=io_addr+FM_LEFT_OFF;
  937.     }
  938.     else wh_card=sb20;  */
  939.     wh_card = sb20;
  940.     return(wh_card);
  941.   }
  942.   sberr = nodsperr;
  943.   return(none);
  944. }
  945.  
  946.  
  947. /**************************************************************************
  948.   cardtype WhichCard()
  949.  
  950.   DESCRIPTION:  Calls various functions to make sure you've
  951.                 got a Sound Blaster
  952.  
  953. **************************************************************************/
  954. cardtype WhichCard(void)
  955. {
  956.   cardtype cret = nodsp;
  957.   short i;
  958.  
  959.   if(get_sb_env()) cret=CheckHard();    // grab environment variable
  960.   if(cret!=nodsp) return(cret);         // If dsp is there, then go home
  961.  
  962.   for(i=0;i<6;i++)                      // scan around for a better io address
  963.   {
  964.     io_addr=ioaddr[i];
  965.  
  966.     cret=CheckHard();
  967.     if(cret!=nodsp) return(cret);
  968.   }
  969.   return(none);                         // Uh oh.
  970. }
  971.  
  972.  
  973. /**************************************************************************
  974.   short SB_Setup()
  975.  
  976.   DESCRIPTION: Sets up the sound blaster for action.  This is the only
  977.                function a programmer should really use.  Most of the
  978.                nitty gritty is handled internally.
  979.  
  980. **************************************************************************/
  981. short SB_Setup(void)
  982. {
  983.   short i,length;
  984.  
  985.   InitT2();                      /* init Timer 2 */
  986.   measure();                     /* time loop factor */
  987.   mue3=mcalc(3) ;               /* calc val for 3 micro sec delay */
  988.   mue23=mcalc(23) ;             /* calc val for 23 micro sec delay */
  989.  
  990.   WhichCard();                  // Go and check the hardware
  991.  
  992.   if(wh_card==none) return(FALSE);
  993.  
  994.                                // Get DSP ready
  995.   dsp_vers=DSP_GetVersion();
  996.   DSP_Write(DSP_SPKR_ON);
  997.  
  998.  
  999.   // Allocate space for playback buffer
  1000.   // For protected mode a special function is used to get REAL memory
  1001.   // that the DMA can find
  1002.   dma_buffer = (BYTE*)real_malloc(2*dma_bufferlen,&realhandle);
  1003. //  dma_buffer = (BYTE*)low_malloc(2*dma_bufferlen,&realhandle);
  1004.  
  1005.   if(!dma_buffer) {
  1006.     sberr = nomem;
  1007.     return(FALSE);
  1008.   }
  1009.                                 // Allocate space for the play ahead buffer
  1010.   playahead_buffer = (BYTE *)malloc(dma_bufferlen+5);
  1011.   if(!playahead_buffer) {
  1012.     sberr = nomem;
  1013.     return(FALSE);
  1014.   }
  1015.                                 // Allocate space for Mixing buffer
  1016.   mix_buffer = (short *)malloc(dma_bufferlen*2+10);
  1017.   if(!mix_buffer) {
  1018.     sberr = nomem;
  1019.     return(FALSE);
  1020.   }
  1021.                                 // Clear the buffer
  1022.   for(i = 0; i < dma_bufferlen+4; i++) {
  1023.     *(dma_buffer+i) = 127;
  1024.     *(playahead_buffer+i) = 127;
  1025.   }
  1026.   SetRate(11000);               // Set the sample rate
  1027.  
  1028.   //mpu_available = MPU_Reset();  // Check for an MPU chip
  1029.   midi_patchmap = defaultpatchmap;
  1030.  
  1031.    return(TRUE);
  1032. }
  1033.  
  1034.  
  1035. /**************************************************************************
  1036.   DWORD far2long(char far *adr)
  1037.  
  1038.   DESCRIPTION: This is used by dma_set to convert a regular far address
  1039.                to a 20 bit flat address.
  1040.  
  1041. **************************************************************************/
  1042. DWORD far2long(char *adr)
  1043. {
  1044.   return(((DWORD)FP_SEG(adr)<<4)+FP_OFF(adr));
  1045. }
  1046.  
  1047.  
  1048. /**************************************************************************
  1049.   void SetRate(WORD rate)
  1050.  
  1051.   DESCRIPTION:  Sets the sample rate (specified in hz)
  1052.  
  1053. **************************************************************************/
  1054. void SetRate(WORD rate)
  1055. {
  1056.   DWORD val;
  1057.  
  1058.   if(rate<4000) return;               // Calculate number for the sound card
  1059.   val=256-1000000L/rate;
  1060.   DSP_Write(DSP_SAMPLE_RATE);
  1061.   DSP_Write((BYTE)val);
  1062.  
  1063.   sample_rate = rate;                 // FYI - This helps other functions
  1064.                                       // To know how fast the DSP is going
  1065. }
  1066.  
  1067. /**************************************************************************
  1068.   WORD dma_set(DWORD adrl,WORD len,short channel)
  1069.  
  1070.   DESCRIPTION:  This programs the DMA controller to start a single pass
  1071.                 output transfer.
  1072.  
  1073.                 (Draeden of VLA has provided some good information for
  1074.                 DMA programming in his INTRO to DMA document)
  1075.  
  1076. **************************************************************************/
  1077. void dma_set(BYTE *sound_address,WORD len,BYTE channel)
  1078. {
  1079.   WORD adr;
  1080.   DWORD adrl;
  1081.   BYTE page;
  1082.  
  1083. //  adrl = far2long(sound_address);     // convert address to 20 bit format
  1084.   adrl=(int)sound_address;  //don't need to convert already have 20 bit form
  1085.   adr=(WORD)adrl;                     // extract page address
  1086.   page=(BYTE)(adrl>>16);              // extract page number
  1087.  
  1088.                       // PREPARE DMA.
  1089.                       //   (Channels 0-3 have different
  1090.                       //   command ports than 4-7.)
  1091.  
  1092.                       // SET CHANNEL, MASK BIT AND MODE
  1093.  
  1094.   if(channel <4) {                    // Chanels 0-3?
  1095.     outp(0x0a,channel+4);          // write channel number with 3rd bit set
  1096.     outp(0x0c,0);                  // Clear Byte Pointer
  1097.  
  1098.                                       // Set the mode.  The mode is determined
  1099.                       // in Go_Varmint().
  1100.     outp(0x0b,DMA_controlbyte+channel);
  1101.   }
  1102.   else {                              // channels 4-7
  1103.     outp(0xd4,channel);            // write channel number
  1104.     outp(0xd8,0);                  // Clear Byte Pointer
  1105.  
  1106.                                       // Set the mode.  The mode is determined
  1107.                       // in Go_Varmint().
  1108.     outp(0xd6,DMA_controlbyte+channel);
  1109.   }
  1110.                                       // SET TRANSFER INFORMATION
  1111.  
  1112.   outp(dma_adr[channel],adr&0xff);// Write address low byte
  1113.   outp(dma_adr[channel],adr>>8);  // Write address high byte
  1114.  
  1115.   outp(dma_len[channel],len&0xff);// Write length  low byte
  1116.   outp(dma_len[channel],len>>8);  // Write length  high byte
  1117.  
  1118.   outp(dma_page[channel],page);   // Write page
  1119.  
  1120.                                       // CLEAR MASK BITS
  1121.   if(channel < 4) outp(0x0a,channel);
  1122.   else outp(0xd4,channel & 0x03);
  1123.  
  1124. }
  1125.  
  1126. /**************************************************************************
  1127.   void polldma(BYTE channel)
  1128.  
  1129.   DESCRIPTION:  This function poles the DMA controller to find out how many
  1130.                 bytes are left in the current transfer.
  1131.  
  1132.                 As of version 0.4, this function is no longer used, but
  1133.                 I thought it might be useful to someone else, so I've only
  1134.                 commented it out.
  1135. **************************************************************************/
  1136. /*WORD polldma(BYTE channel)
  1137. {
  1138.   BYTE low1,high1,low2,high2;
  1139.  
  1140.   disable_int(intnr);             // Turn off the interrupt so we don't get
  1141.                                   // caught with our pants down.
  1142.   asm {
  1143.     mov dx,0x0c                   // Flip the master reset switch
  1144.     mov al,0
  1145.     out dx,al
  1146.   }
  1147.   _DX = dma_len[channel];         // Load in the counter address
  1148.                                   // read position twice, becasue sometimes
  1149.                                   // there is a problem
  1150.   asm{
  1151.     in al,dx                      // read the low byte first
  1152.     mov low1,al
  1153.     in al,dx                      // read the high byte next
  1154.     mov high1,al
  1155.  
  1156.     in al,dx                      // read the low byte first
  1157.     mov low2,al
  1158.     in al,dx                      // read the high byte next
  1159.     mov high2,al
  1160.  
  1161.   }
  1162.   enable_int(intnr);              // Done, so we'll put the interrupt back.
  1163.  
  1164.                                   // High bytes the same? Use second reading
  1165.   if(high1 == high2)return((WORD)high2*256+low2);
  1166.                                   // else the First reading is accurate
  1167.   return(high1*256+low1);
  1168.  
  1169. }*/
  1170.  
  1171.  
  1172.  
  1173. /**************************************************************************
  1174.   static void far interrupt sb_int()
  1175.  
  1176.   DESCRIPTION:  This is the sound Blaster interrupt that is to be
  1177.                 called at the end of DMA transfer.  This is how the flow
  1178.                 of things goes:
  1179.  
  1180.                    Dump last mix to the DMA buffer
  1181.                   Mix regular samples
  1182.                   Mix MOD stuff
  1183.                   Calculate next DMA buffer
  1184.                   acknowledge interrupt
  1185.                   Run the midi stuff.
  1186.  
  1187.         The DOSYNC's are macros define in sound.h designed to
  1188.                 check the vertical retrace and then set a byte so that
  1189.                 these sound functions can be used with games that check
  1190.                 the vertical retrace.
  1191.  
  1192. **************************************************************************/
  1193. void _saveregs interrupt sb_int(void)
  1194. {
  1195.   short i,j;
  1196.   WORD lastbyte;
  1197.   short *mbuf;
  1198.   BYTE *dbuf;
  1199.   static int midi_count = 100;
  1200.  
  1201.   if(debug_intdisable) _disable();
  1202.  
  1203.   inp(io_addr+DSP_RSTATUS);        // Acknowledge DSP interrupt
  1204.  
  1205. //  if(DSP_overhead) timer_on();     // start timer to measure DSP overhead
  1206.  
  1207.                                    // Copy in playahead section of the buffer
  1208.   memcpy(dma_buffer,playahead_buffer,dma_bufferlen+2);
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.   DOSYNC;                          // Macro for checking the vertical retrace
  1215.                                    // clear out the mixing buffer
  1216.   for(j = 0; j < dma_bufferlen+1; j++) *(mix_buffer+j) = 128;
  1217.   DOSYNC;
  1218.  
  1219.                    // Mix in digitized sounds
  1220.   for(i = 0; i <sounds_in_queue; i++) {
  1221.     DOSYNC;
  1222.     if(soundpos[i]>=dma_bufferlen) {// enough left to fill the buffer?
  1223.       for(j = 1; j < dma_bufferlen+1; j++) *(mix_buffer+j) += *(sounddata[i]++);
  1224.       soundpos[i] -= (dma_bufferlen);
  1225.     }
  1226.     else {                         // else play what is left
  1227.       for(j = 1; j <= soundpos[i]; j++) *(mix_buffer+j) += *(sounddata[i]++);
  1228.                                    // delete the sound
  1229.       for(j = i; j < sounds_in_queue;j++) {
  1230.         sounddata[j] = sounddata[j+1];
  1231.         soundpos[j] = soundpos[j+1];
  1232.       }
  1233.       sounds_in_queue--;           // One less sound.
  1234.       i--;                         // make sure we don't skip the next sound
  1235.     }
  1236.   }
  1237.   DOSYNC;
  1238.                                    // Check to make sure that dma_bufferlen
  1239.                                    // is not bigger than the number of bytes
  1240.                                    // between ticks.  If it is, this loop
  1241.                                    // will crash.
  1242.   if(mod_bytespertick < dma_bufferlen) mod_on = FALSE;
  1243.  
  1244.   if(mod_on && mod_data) {         // MOD stuff activated and ready?
  1245.     if(mod_reset) {                // Reset the MOD?
  1246.       for(i = 0; i < 4; i++ ) {    // Reset all four channels
  1247.         chan[i].sdata = NULL;
  1248.         chan[i].offset = 0;
  1249.         chan[i].rlength = 0;
  1250.         chan[i].end = 0;
  1251.     chan[i].volume = 0;
  1252.         chan[i].sample_number = 0;
  1253.         chan[i].position= 0;
  1254.         chan[i].counter = 0;
  1255.         chan[i].pinc = 0;
  1256.         chan[i].effect = 0;
  1257.         chan[i].x = 0;
  1258.         chan[i].y = 0;
  1259.       }
  1260.                                    // Reset global mod variables
  1261.       mod_pattern=mod_data->pattern_data[mod_data->ptable[0]];
  1262.       mod_pstop = mod_pattern+1024;
  1263.       mod_tablepos=0;
  1264.       mod_bytespertick = sample_rate/11000.0 * 220;
  1265.       mod_ticksperdivision = 6;
  1266.       mod_currentbyte = 0;
  1267.       mod_currenttick = 0;
  1268.       mod_divoffset =0;
  1269.  
  1270.       mod_reset = FALSE;           // Reset the reset switch
  1271.     }
  1272.  
  1273.                                    // **************************************
  1274.                                    // This little section mixes all the mod
  1275.                    // channels if the number of bytes left
  1276.                                    // to go until the next tick is bigger
  1277.                                    // than the dma_buffer length.
  1278.                                    // **************************************
  1279.     if(mod_currentbyte > dma_bufferlen) {
  1280.       for(i = 0; i < 4; i++) {     // Loop through the four channels
  1281.         DOSYNC;
  1282.  
  1283.                    // If the volume is zero or if the sample
  1284.                                    // has ended, then there is no need to mix
  1285.                                    // anything.
  1286.         if(chan[i].volume && chan[i].position <= chan[i].end) {
  1287.                                    // Loop along the length of the mixing buffer
  1288.           for(j = 0; j < dma_bufferlen+1; j++) {
  1289.                                    // Add this byte to the mixing buffer
  1290.             *(mix_buffer+j) += (*(chan[i].sdata + chan[i].position) * chan[i].volume)>>mod_volume;
  1291.                    // Here is where the frequency magic
  1292.                                    // happens.  I use fixed point arithmatic
  1293.                                    // to increment the sample position pointer
  1294.                                    // at different rates.
  1295.             chan[i].counter += chan[i].pinc;
  1296.             chan[i].position += chan[i].counter>>8;
  1297.             chan[i].counter &= 0x00ff;
  1298.                                    // Are we at the end of the sample?
  1299.         if(chan[i].position >= chan[i].end) {
  1300.                                    // Repeating?  Move the position back.
  1301.               if(chan[i].rlength > 1) {
  1302.                 chan[i].position = chan[i].offset;
  1303.                 chan[i].counter = 0;
  1304.                 chan[i].end = chan[i].offset+chan[i].rlength;
  1305.               }
  1306.  
  1307.           else break;          // else Jump out of mixing loop
  1308.             }
  1309.           }
  1310.         }
  1311.       }
  1312.                                    // Keep track of where we are.
  1313.       mod_currentbyte -= dma_bufferlen+1;
  1314.     }
  1315.                    // **************************************
  1316.                                    // This little section mixes all the mod
  1317.                                    // channels if the number of bytes left
  1318.                                    // to go until the next tick is *smalleer*
  1319.                                    // than the dma_buffer length.
  1320.                                    //
  1321.                                    // It first mixes what is left, then it
  1322.                                    // decrements the tick and calls out
  1323.                    // to the module handling routines.
  1324.                                    // Once that is donde, it mixes the
  1325.                                    // rest of the DMA buffer.
  1326.                                    //
  1327.                                    // The two mixing routines are extacly the
  1328.                                    // same as the one above except the first
  1329.                                    // one loops over the first part of the
  1330.                                    // mixing buffer, and the second mixes
  1331.                    // over the rest.
  1332.                                    // **************************************
  1333.  
  1334.     else {
  1335.                                    // Mix the first part of the buffer
  1336.       for(i = 0; i < 4; i++) {
  1337.         DOSYNC;
  1338.         if(chan[i].volume && chan[i].position <= chan[i].end) {
  1339.       for(j = 0; j < mod_currentbyte+1; j++) {
  1340.             *(mix_buffer+j) += (*(chan[i].sdata + chan[i].position) * chan[i].volume)>>mod_volume;
  1341.  
  1342.             chan[i].counter += chan[i].pinc;
  1343.             chan[i].position += chan[i].counter>>8;
  1344.             chan[i].counter &= 0x00ff;
  1345.  
  1346.             if(chan[i].position >= chan[i].end) {
  1347.           if(chan[i].rlength > 1) {
  1348.                 chan[i].position = chan[i].offset;
  1349.                 chan[i].counter = 0;
  1350.                 chan[i].end = chan[i].offset+chan[i].rlength;
  1351.               }
  1352.               else break;
  1353.             }
  1354.           }
  1355.     }
  1356.       }
  1357.  
  1358.       lastbyte = mod_currentbyte+1;  // Keep track of where we are inthe buffer
  1359.  
  1360.                                    // Ready for next division?
  1361.       if(mod_currenttick >= mod_ticksperdivision * (mod_patterndelay+1) ) {
  1362.         mod_patterndelay = 0;      // Reset pattern delay
  1363.     dodiv();                   // Handle the division commands.
  1364.         DOSYNC;
  1365.                                    // Are we at the end of the pattern?
  1366.         if(mod_pattern == mod_pstop) {
  1367.           mod_tablepos++;          // Next table!
  1368.  
  1369.                                    // Done with tables?  Done with MOD.
  1370.           if(mod_tablepos == mod_data->num_positions) mod_on = FALSE;
  1371.       else {                   // Otherwise, set pointer to next table
  1372.             mod_pattern = mod_data->pattern_data[mod_data->ptable[mod_tablepos]];
  1373.             mod_pstop = mod_pattern+1024;
  1374.           }
  1375.         }
  1376.         mod_currenttick = 0;       // Reset the tick counter
  1377.       }
  1378.                                    // Reset the byte counter
  1379.       mod_currentbyte = mod_bytespertick;
  1380.  
  1381.       mod_currenttick++;           // Do our tick stuff.
  1382.       dotick();
  1383.       DOSYNC;
  1384.                                    // Mix the rest of the buffer
  1385.       for(i = 0; i < 4; i++) {
  1386.         DOSYNC;
  1387.     if(chan[i].volume && chan[i].position <= chan[i].end) {
  1388.           for(j = lastbyte; j < dma_bufferlen+1; j++) {
  1389.             *(mix_buffer+j) += (*(chan[i].sdata + chan[i].position) * chan[i].volume)>>mod_volume;
  1390.  
  1391.             chan[i].counter += chan[i].pinc;
  1392.             chan[i].position += chan[i].counter>>8;
  1393.             chan[i].counter &= 0x00ff;
  1394.  
  1395.         if(chan[i].position >= chan[i].end) {
  1396.               if(chan[i].rlength > 1) {
  1397.                 chan[i].position = chan[i].offset;
  1398.                 chan[i].counter = 0;
  1399.                 chan[i].end = chan[i].offset+chan[i].rlength;
  1400.               }
  1401.               else break;
  1402.             }
  1403.       }
  1404.         }
  1405.       }
  1406.                                    // Update our position
  1407.       mod_currentbyte -= (dma_bufferlen-lastbyte +1);
  1408.     }
  1409.  
  1410.     DOSYNC;
  1411.   }
  1412.  
  1413.  
  1414.                                    // Write mixed stuff to the playback buffer
  1415.   for(mbuf = mix_buffer, dbuf = playahead_buffer;
  1416.       mbuf != mix_buffer+dma_bufferlen+2;
  1417.       mbuf++) {
  1418.     if(*mbuf > 254) *mbuf = 254;       // Clip overload values
  1419.     else if(*mbuf < 1) *mbuf = 1;
  1420.     *(dbuf++) = *mbuf;
  1421.   }
  1422.   DOSYNC;
  1423.  
  1424.                                         // * BLACK MAGIC *  Setting this byte
  1425.                                        // prevents static that seems to
  1426.                                        // be caused when other interrupts
  1427.                        // get interrupted by this one.
  1428.   if(debug_antistatic) *dma_buffer = *(dma_buffer+dma_bufferlen);
  1429.  
  1430.  
  1431.   if(card_id < 3) {                        // Not SB 2.0?
  1432.                                           // Set up DMA for one-shot
  1433.     dma_set(dma_buffer,dma_bufferlen,dma_ch);
  1434.     DSP_Write(0x14);                       // One shot DMA DAC (8bit)
  1435.     DSP_Write((dma_bufferlen) & 0xff);  // Write length low byte
  1436.     DSP_Write((dma_bufferlen) >> 8);    // Write length high byte
  1437.   }
  1438.  
  1439.  
  1440.   DOSYNC;
  1441.  
  1442.  
  1443.                    // Varmint's system clock
  1444.   vclock ++;                       // Vertical retrace sync clock
  1445.   vsyncclock ++;
  1446.  
  1447.                                    // MIDI stuff first
  1448.   midi_count-= 100;
  1449.   if(midi_count < 100) {
  1450.     MidiPlayer();                  // Call a midi player
  1451.     midi_count += midi_callfreq * midi_usertempo*100.0; // reset counter
  1452.     DOSYNC;
  1453.   }
  1454.  
  1455. //  if(DSP_overhead) DSP_overhead = timer_off();//  How long did this take?
  1456.  
  1457.   if(debug_intdisable) _enable();
  1458.   if(intnr < 8) outp(0x20,0x20);   // Clear PIC
  1459.   else outp(0xa0,0x20);
  1460.  
  1461. }
  1462.  
  1463.  
  1464.  
  1465. /**************************************************************************
  1466.   void SB_SetVect()
  1467.  
  1468.   DESCRIPTION:  Installs the DMA interrupt vector.  This makes it so that
  1469.                 sb_int() is called whenever a DMA transfer is finished
  1470.  
  1471. **************************************************************************/
  1472. void SB_SetVect(void)
  1473. {
  1474.   orgirqint=_dos_getvect(int2vect(intnr));
  1475.   _dos_setvect(int2vect(intnr),handlerint);     /* set vector to our routine */
  1476.   enable_int(intnr);                       /* enable sb interrupt */
  1477. }
  1478.  
  1479.  
  1480. /**************************************************************************
  1481.   void SB_RemoveVect()
  1482.  
  1483.   DESCRIPTION:  Removes the DMA interrupt vector
  1484.  
  1485. **************************************************************************/
  1486. void SB_RemoveVect(void)
  1487. {
  1488.   disable_int(intnr);                     /* disable sb interrupt */
  1489.   _dos_setvect(int2vect(intnr),orgirqint);      /* restore org intr vector */
  1490. }
  1491.  
  1492.  
  1493. /* --------------------------------------------------- */
  1494.  
  1495. /* timerX routines are following
  1496.  
  1497.   These routines are for highly accurate time measurements
  1498.  
  1499. */
  1500.  
  1501.  
  1502. /**************************************************************************
  1503.   void InitT2()
  1504.  
  1505.   DESCRIPTION: Initializes speaker timer for timing operations.
  1506.  
  1507. **************************************************************************/
  1508. void InitT2(void)
  1509. {
  1510.                                      // Disable speaker output, but keep
  1511.                                      // timer 2 enabled.
  1512.   outp(0x61,(inp(0x61)&0xfd) | 0x01);
  1513. }
  1514.  
  1515.  
  1516. /**************************************************************************
  1517.   void timer_on()
  1518.  
  1519.   DESCRIPTION: Turns on timer counter for a time measurement
  1520.  
  1521. **************************************************************************/
  1522. void timer_on(void)
  1523. {
  1524.   outp(0x43,0xb0);                 // Set up the timer for countdown
  1525.   outp(0x42,0xff);                // Least significant byte
  1526.   outp(0x42,0xff);                // Most significant byte
  1527.  
  1528. }
  1529.  
  1530.  
  1531. /**************************************************************************
  1532.   WORD timer_off()
  1533.  
  1534.   DESCRIPTION: Turns off time and reports clicks elapsed.  Note that this
  1535.                timer is so quick that it is wraps after only 56
  1536.                milliseconds.  If you want to timer longer stuff, I suggest
  1537.                using the global variable vclock.  It's tick frequency is
  1538.                sample_rate / dma_bufferlen.
  1539.  
  1540. **************************************************************************/
  1541. WORD timer_off(void)
  1542. {
  1543. /*
  1544.   outp(0x43,0xc0);                 // Read the timer countdown status
  1545.   timer_hold = inp(0x42) + inp(0x42) * 256;
  1546.  
  1547.   timer_diff = 0xffff - timer_hold;   // timer_diff is used later
  1548.   return timer_diff;
  1549.   */
  1550. }
  1551.  
  1552.  
  1553. /**************************************************************************
  1554.   WORD to_micro(WORD clk)
  1555.  
  1556.   DESCRIPTION: Converts clock ticks number to microsecs
  1557.  
  1558. **************************************************************************/
  1559. WORD to_micro(WORD clk)
  1560. {
  1561.     return(clk*838/1000);
  1562. }
  1563.  
  1564.  
  1565.  
  1566. /**************************************************************************
  1567.   void measure()
  1568.  
  1569.   DESCRIPTION: measures a standard delay loop for other delay functions
  1570.  
  1571. **************************************************************************/
  1572. void measure(void)
  1573. {
  1574.   register i=10000;
  1575.  
  1576. /*  _disable();                      // Disable interrupts
  1577.   timer_on();                      // Start the timer
  1578.   while(i--);                      // Count to 10000
  1579.   timer_val = timer_off();         // read the timer
  1580.   _enable();                       // Enable interrupts
  1581. */
  1582.   timer_val=1000;
  1583.  
  1584.   mue999 = mcalc(990);             // Calculate a millisecond
  1585. }
  1586.  
  1587.  
  1588. /**************************************************************************
  1589.   void mdelay(WORD delay)
  1590.  
  1591.   DESCRIPTION: Very tiny delay
  1592.  
  1593. **************************************************************************/
  1594. void mdelay(WORD delay)
  1595. {
  1596.   register i = delay;
  1597.   while(i--);
  1598. }
  1599.  
  1600.  
  1601. /**************************************************************************
  1602.   void _saveregs msdelay(WORD delay)
  1603.  
  1604.   DESCRIPTION:  Millisec delay.  When using this library, you should
  1605.                 use this delay for millisecond delays instead of the delay
  1606.                 function that comes with turbo C.
  1607.  
  1608. **************************************************************************/
  1609. void _saveregs msdelay(WORD delay)
  1610. {
  1611.   WORD i;
  1612.  
  1613.   for(i=0;i<delay;i++) mdelay(mue999); // mdelay(mue999) = 1 millisec
  1614. }
  1615.  
  1616.  
  1617. /**************************************************************************
  1618.   WORD mcalc(WORD micro)
  1619.  
  1620.   DESCRIPTION:  Calculates number of ticks to send to mdelay for a specified
  1621.   number of microseconds.
  1622.  
  1623. **************************************************************************/
  1624. WORD mcalc(WORD micro)
  1625. {
  1626.   return(WORD)((long)micro*10000L/timer_val*1000/838);
  1627. }
  1628.  
  1629.                                       /********************************
  1630.  
  1631.                                                 TIMER 0 STUFF
  1632.  
  1633.  
  1634.  
  1635.  
  1636.                                       *********************************/
  1637. /* --------------------------------
  1638.  
  1639. CAUTION: These routines can cause a lot of headaches while debugging.
  1640. If you set your own interrupt and then stop the program before you call
  1641. Remove_Timer0(), you'd better reboot your computer, because very
  1642. unpredictable things will happen if Install_Timer0() is called again.
  1643. My suggestion is to get your interrupt working and then comment out the
  1644. Timer0 routines until the rest of the program is written and debugged.
  1645.                                       - Eric  */
  1646.  
  1647. /**************************************************************************
  1648.   static void interrupt timerint()
  1649.  
  1650.   DESCRIPTION: THis is the actual interrupt function stored in the timer
  1651.            0 slot (short 08).   This calls the old int08 function
  1652.                at proper intervals as well as the user specified function
  1653.  
  1654. **************************************************************************/
  1655. static void interrupt timerint(void)
  1656. {
  1657.  
  1658.   timer_on();                      // set timer for overhead calculation.
  1659.   call_func();                     // user specified function
  1660.  
  1661.                                    // Now let's do some fancy counting so
  1662.                                    // we can call the system clock at the
  1663.                                    // right moments.
  1664.   if(timsum<100)
  1665.   {
  1666.     timsum+=timadd;
  1667.     orgtick();
  1668.   }
  1669.   else
  1670.   {
  1671. //    asm mov al,0x20;
  1672. //    asm out 0x20,al;
  1673.   }
  1674.   timsum-=100;                     // decrement our special timer
  1675. }
  1676.  
  1677.  
  1678. /**************************************************************************
  1679.   void Install_Timer0(WORD period,void far (*func)())
  1680.  
  1681.   DESCRIPTION: This sets up timer0 to call your function at the specified
  1682.                period.
  1683.  
  1684. **************************************************************************/
  1685. void Install_Timer0(WORD period,void (*func)(void))
  1686. {
  1687.    if(!func) return;       /* no valid func ptr */
  1688.   call_func=func;
  1689.  
  1690.   timadd= (WORD)(6553600L/period); // counting seed for timerint()
  1691.   timsum=0;                 // start counter at 0
  1692.  
  1693. //  asm mov al,0x36            /* program timer 0 with modus 3 */
  1694. //  asm out 0x43,al            /* and counter value of period  */
  1695. //  asm mov ax,period
  1696. //  asm out 0x40,al
  1697. //  asm mov al,ah
  1698. //  asm out 0x40,al
  1699.  
  1700.   orgtick= _dos_getvect(8);       // Remember the old interrupt
  1701.   _dos_setvect(8,timerint);      // put in a new one.
  1702. }
  1703.  
  1704.  
  1705. /**************************************************************************
  1706.   void Remove_Timer0()
  1707.  
  1708.   DESCRIPTION:  Removes your goofy interrupt, 'cause we didn't want
  1709.                 it anyway!  :P
  1710.  
  1711. **************************************************************************/
  1712. void Remove_Timer0(void)
  1713. {
  1714.   if(!orgtick) return;      // Must have called Install_Timer0 first
  1715. //  asm mov al,0x36            /* program timer 0 with modus 3 */
  1716. //  asm out 0x43,al            /* and counter value of 0 (2^16)*/
  1717. //  asm mov al,0
  1718. //  asm out 0x40,al
  1719. //  asm out 0x40,al
  1720.   _dos_setvect(8,orgtick);       // put back original vector
  1721. }
  1722.  
  1723.  
  1724.  
  1725. /**************************************************************************
  1726.   BYTE int2vect(BYTE intnr)
  1727.  
  1728.   DESCRIPTION:  This function converts a PIC irq number to a true
  1729.                 interrupt vector number.  For PC's with a 286 or greater,
  1730.                 irq's 0-7  refer to interrupts 0x08 - 0x0F and
  1731.                 irq's 8-15 refer to interrupts 0x70 - 0x77.
  1732.  
  1733. **************************************************************************/
  1734. BYTE int2vect(BYTE intnr)
  1735. {
  1736.   if(intnr>7) return(intnr + 0x68);
  1737.   else return(intnr+8);
  1738. }
  1739.  
  1740.  
  1741. /**************************************************************************
  1742.   void enable_int(BYTE nr)
  1743.  
  1744.   DESCRIPTION:  Enables an IRQ interrupt using the Programmable
  1745.                 interrupt controller (PIC)
  1746.  
  1747.                 To enable a interrupt, you want to turn its PIC bit off.
  1748.                 Let's say that you want to turn on interrupt 3.  The
  1749.                 code works something like this:
  1750.  
  1751.  
  1752.                     BIT:                 76543210
  1753.  
  1754.                     1 << nr             00001000
  1755.                     ~(1 << nr)          11110111 (mask)
  1756.                                         01001101 (setting)
  1757.                     setting & mask      01000101
  1758.                                             ^
  1759.                                             |
  1760.                           Notice how bit 3 is set to zero.
  1761.  
  1762. **************************************************************************/
  1763. void enable_int(BYTE nr)
  1764. {
  1765.   BYTE mask,setting;
  1766.  
  1767.   if(nr<8) {                             // First controller?
  1768.     mask = ~(1 << nr);                  // Create interrupt mask
  1769.     setting = inp(0x21) & mask;     // Turn off the proper bit
  1770.     outp(0x21,setting);             // Write back the result
  1771.   }
  1772.   else {                                // Second Controller?
  1773.     mask = ~(1 << (nr-8));              // Create interrupt mask
  1774.     setting = inp(0xa1) & mask;     // Turn off the proper bit
  1775.     outp(0xa1,setting);             // Write back the result
  1776.   }
  1777. }
  1778.  
  1779.  
  1780. /**************************************************************************
  1781.   void disable_int(BYTE nr)
  1782.  
  1783.   DESCRIPTION:  Disables an IRQ interrupt using the Programmable
  1784.                 interrupt controller.
  1785.  
  1786.                 To disable a interrupt, you want to turn its PIC bit on.
  1787.                 Let's say that you want to turn off interrupt 3.  The
  1788.                 code works something like this:
  1789.  
  1790.  
  1791.                     BIT:                 76543210
  1792.  
  1793.                     1 << nr             00001000
  1794.                     ~(1 << nr)          11110111 (mask)
  1795.                                         01000101 (setting)
  1796.                     ~setting            10111010
  1797.                     (~setting) & mask    10110010 (new value of setting)
  1798.                     ~setting            01001101
  1799.  
  1800.                                             ^
  1801.                                             |
  1802.                           Notice how bit 3 is set to one.
  1803.  
  1804. **************************************************************************/
  1805. void disable_int(BYTE nr)
  1806. {
  1807.   BYTE mask,setting;
  1808.  
  1809.   if(nr<8) {                            // First controller?
  1810.     mask = ~(1 << nr);                  // Create interrupt mask
  1811.     setting = (~inp(0x21)) & mask;  // Turn on the proper bit
  1812.     outp(0x21,~setting);            // Write back the result
  1813.   }
  1814.   else {                                // Second Controller?
  1815.     mask = ~(1 << (nr-8));              // Create interrupt mask
  1816.     setting = (~inp(0xa1)) & mask;  // Turn on the proper bit
  1817.     outp(0xa1,~setting);            // Write back the result
  1818.   }
  1819. }
  1820.  
  1821.  
  1822. /**************************************************************************
  1823.   short getvoice(VOICE v[],short track,short channel, short note)
  1824.  
  1825.   DESCRIPTION: Find the first matching voice (or first inactive voice if
  1826.                 a match is not found).   This function is used by midiplayer()
  1827.                 as an interface to get FM voices.
  1828.  
  1829.   RETURNS:
  1830.     Open number if successful, -1 if not.
  1831. **************************************************************************/
  1832. short getvoice(VOICE v[],short track,short channel, short note)
  1833. {
  1834.   short i;
  1835.  
  1836.  
  1837.   for(i = 0; i < 9; i++) {              // find matching active note
  1838.     if(v[i].active) {
  1839.       if(v[i].owner_track == track &&
  1840.          v[i].owner_channel == channel &&
  1841.          v[i].note == note) return(i);
  1842.  
  1843.     }
  1844.   }
  1845.                                         // no note, so find first inactive voice
  1846.  
  1847.   for(i = 0; i < 9; i++) {
  1848.     if(!v[i].active) return(i);
  1849.   }
  1850.                                         // no available voices... error
  1851.   return -1;
  1852. }
  1853.  
  1854. /**************************************************************************
  1855.   void dotick(void)
  1856.  
  1857.   DESCRIPTION:  Handles ongoing MOD commands at each tick.
  1858.  
  1859. **************************************************************************/
  1860. void dotick(void)
  1861. {
  1862.   short i,k;                              // Local variable we need
  1863.   WORD period,rate;
  1864.   BYTE e1,e2;
  1865.   float vibspot;
  1866.  
  1867.   for(i = 0; i < 4; i++) {                // Loop through all four channels
  1868.     e1 = chan[i].effect;                  // Get info aboput what is going on
  1869.     e2 = chan[i].x;
  1870.  
  1871.     if(chan[i].retrigger) {               // Check for a retrigger signal
  1872.                                           // Time to retrigger?
  1873.       if(!(mod_currenttick % chan[i].retrigger)) {
  1874.         chan[i].position = 0;
  1875.         chan[i].counter = 0;
  1876.         chan[i].end = mod_data->slength[chan[i].sample_number-1];
  1877.       }
  1878.     }
  1879.  
  1880.     if(chan[i].cut > -1) {                // Check for a cut signal
  1881.       if(mod_currenttick >= chan[i].cut) chan[i].volume = 0;
  1882.     }
  1883.  
  1884.     switch(e1) {
  1885.       case 0:                              // Arpeggio
  1886.         chan[i].count++;
  1887.         switch(chan[i].count % 3) {
  1888.           case 0:
  1889.             chan[i].pinc = chan[i].data1;
  1890.             break;
  1891.           case 1:
  1892.             chan[i].pinc = chan[i].data2;
  1893.             break;
  1894.           case 2:
  1895.             chan[i].pinc = chan[i].data3;
  1896.             break;
  1897.         }
  1898.         break;
  1899.       case 1:                              // Slide up
  1900.                                              // glissando = chromatic slide
  1901.         if(!mod_glissando) chan[i].period -= chan[i].porta;
  1902.         else for(k =0; k < chan[i].porta; k++) chan[i].period *= UP_SEMITONE;
  1903.                                              // Don't go too high
  1904.         if(chan[i].period < 1) chan[i].period = 1;
  1905.                                              // Set frequency counters
  1906.         rate = 7093789.2/(2*chan[i].period);
  1907.         chan[i].pinc = (rate * 256.0)/sample_rate;
  1908.         break;
  1909.       case 2:                              // slide down
  1910.         if(!mod_glissando) chan[i].period += chan[i].porta;
  1911.                                              // glissando = chromatic slide
  1912.         else for(k =0; k < chan[i].porta; k++) chan[i].period *= DOWN_SEMITONE;
  1913.                                              // Don't go too low
  1914.         if(chan[i].period > 2000) chan[i].period = 2000;
  1915.                                              // Set frequency counters
  1916.         rate = 7093789.2/(2*chan[i].period);
  1917.         chan[i].pinc = (rate * 256.0)/sample_rate;
  1918.         break;
  1919.       case 3:                              // slide to note
  1920.                                              // Slide up or down? Each case is
  1921.                                              // just like regular up and down
  1922.                                              // slides.
  1923.         if(chan[i].period < chan[i].period2) {
  1924.           if(!mod_glissando) chan[i].period += chan[i].porta;
  1925.           else for(k =0; k < chan[i].porta; k++) chan[i].period *= DOWN_SEMITONE;
  1926.           if(chan[i].period > chan[i].period2) chan[i].period = chan[i].period2;
  1927.         }
  1928.         else if(chan[i].period > chan[i].period2) {
  1929.           if(!mod_glissando) chan[i].period -= chan[i].porta;
  1930.           else for(k =0; k < chan[i].porta; k++) chan[i].period *= UP_SEMITONE;
  1931.           if(chan[i].period < chan[i].period2) chan[i].period = chan[i].period2;
  1932.         }
  1933.                                              // Set frequency counters
  1934.         rate = 7093789.2/(2*chan[i].period);
  1935.         chan[i].pinc = (rate * 256.0)/sample_rate;
  1936.         break;
  1937.       case 4:                              // vibrato
  1938.                                              // Calculate current waveform
  1939.         vibspot = chan[i].vibperiod/32.0 *
  1940.                   (double)mod_currenttick/mod_ticksperdivision * M_PI;
  1941.                                              // Adjust the period
  1942.         period = chan[i].period + chan[i].vibdepth * vibspot;
  1943.                                              // Set frequency counters
  1944.         rate = 7093789.2/(2* period);
  1945.         chan[i].pinc = (rate * 256.0)/sample_rate;
  1946.  
  1947.         break;
  1948.       case 5:                             // Cont. Slide to note + vol. Slide
  1949.         if(chan[i].period < chan[i].period2) {
  1950.           chan[i].period += chan[i].porta;
  1951.           if(chan[i].period > chan[i].period2) chan[i].period = chan[i].period2;
  1952.         }
  1953.         else if(chan[i].period > chan[i].period2) {
  1954.           chan[i].period -= chan[i].porta;
  1955.           if(chan[i].period < chan[i].period2) chan[i].period = chan[i].period2;
  1956.         }
  1957.         rate = 7093789.2/(2*chan[i].period);
  1958.         chan[i].pinc = (rate * 256.0)/sample_rate;
  1959.  
  1960.         chan[i].volume += chan[i].vslide;
  1961.         if(chan[i].volume < 0) chan[i].volume = 0;
  1962.         if(chan[i].volume > 64) chan[i].volume = 64;
  1963.         break;
  1964.       case 6:                              // Vibrato + volume slide
  1965.         vibspot = chan[i].vibperiod/32.0 *
  1966.                   (double)mod_currenttick/mod_ticksperdivision * M_PI;
  1967.         period = chan[i].period + chan[i].vibdepth * vibspot;
  1968.         rate = 7093789.2/(2* period);
  1969.         chan[i].pinc = (rate * 256.0)/sample_rate;
  1970.  
  1971.         chan[i].volume += chan[i].vslide;
  1972.         if(chan[i].volume < 0) chan[i].volume = 0;
  1973.         if(chan[i].volume > 64) chan[i].volume = 64;
  1974.         break;
  1975.       case 7:                              // Tremolo
  1976.                                              // Just like Vibrato except with
  1977.                                              // this modulates sample volume
  1978.        vibspot = chan[i].vibperiod/32.0 *
  1979.                   (double)mod_currenttick/mod_ticksperdivision * M_PI;
  1980.         chan[i].volume = chan[i].volume2 + chan[i].vibdepth * vibspot;
  1981.         if(chan[i].volume < 0) chan[i].volume = 0;
  1982.         if(chan[i].volume > 64) chan[i].volume = 64;
  1983.         break;
  1984.       case 10:                            // Volume slide
  1985.         chan[i].volume += chan[i].vslide;    // change the volume.
  1986.                                              // Clip.
  1987.         if(chan[i].volume < 0) chan[i].volume = 0;
  1988.         if(chan[i].volume > 64) chan[i].volume = 64;
  1989.         break;
  1990.       case 14:
  1991.         switch(e2) {
  1992.           case 13:                         //  Delay sample
  1993.                                              // data4 is decremented on each
  1994.                                              // Pass.  When it gets to zero,
  1995.                                              // the sample volume is turned
  1996.                                              // on.
  1997.             if(!chan[i].data4) chan[i].volume = chan[i].data3;
  1998.             chan[i].data4--;
  1999.             break;
  2000.           default:
  2001.             break;
  2002.         }
  2003.         break;
  2004.       case 15:
  2005.         break;
  2006.       default:
  2007.         break;
  2008.     }
  2009.  
  2010.     chan[i].volume *= channel_select[i];  // THis allows the user to mask
  2011.                                           // channels.
  2012.   }
  2013. }
  2014. /**************************************************************************
  2015.   void dodiv(void)
  2016.  
  2017.   DESCRIPTION:  Handles the commands found at a module division.
  2018.  
  2019. **************************************************************************/
  2020. void dodiv(void)
  2021. {
  2022.   short i,j,k;                              // Local variables we'll need
  2023.   short samp,pattern_break = FALSE,position_jump = FALSE,loop = FALSE;
  2024.   WORD period,rate;
  2025.   BYTE e1,e2,e3;
  2026.   float num;
  2027.  
  2028.   for(i = 0; i < 4; i++) {                // Loop through all four channels
  2029.     chan[i].retrigger = 0;                // Reset retrigger and cut signals
  2030.     chan[i].cut  = -1;
  2031.                                           // Grab information for this channel
  2032.     samp = (*(mod_pattern)&0xF0) + ((*(mod_pattern+2) & 0xf0)>>4);
  2033.     period = (*(mod_pattern)&0x0F)*256 + *(mod_pattern+1);
  2034.     e1 = (*(mod_pattern+2)) & 0x0F;       // e1-e3 are the command nibbles
  2035.     e2 = (*(mod_pattern+3)  & 0xF0) >> 4;
  2036.     e3 = (*(mod_pattern+3)) & 0x0F;
  2037.  
  2038.     if(samp && e1 != 3) {                 // set a new sample?
  2039.  
  2040.       chan[i].sample_number = samp;       // Some MOD commmands need this
  2041.       chan[i].sdata = mod_data->sdata[samp-1]; // set a pointer to the data
  2042.       chan[i].position = 0;               // Retrigger the sample
  2043.       chan[i].counter = 0;
  2044.                                           // store sample characteristics
  2045.       chan[i].offset = mod_data->offset[samp-1];
  2046.       chan[i].rlength = mod_data->repeat[samp-1];
  2047.                                           // Keep track of end so we know
  2048.                                           // When to stop.
  2049.       chan[i].end = mod_data->slength[samp-1];
  2050.                                           // Set the volume to the default
  2051.       chan[i].volume = mod_data->volume[samp-1];
  2052.  
  2053.     }
  2054.  
  2055.     if(period && e1 != 3) {               // Set a new period?
  2056.                                           // Calculate adjusted period
  2057.       chan[i].period = period + mod_data->finetune[chan[i].sample_number-1]
  2058.                               + mod_finetune;
  2059.                                           // Set frequency counter
  2060.       rate = 7093789.2/(2*period);
  2061.       chan[i].pinc = (rate*256.0)/sample_rate;
  2062.     }
  2063.  
  2064.  
  2065.     chan[i].effect = e1;                   // Keep for reference in dotick()
  2066.     chan[i].x = e2;
  2067.     chan[i].y = e3;
  2068.  
  2069.     switch(e1) {                          // Process the commands
  2070.       case 0:                              // Arpeggio
  2071.         chan[i].data1 = chan[i].pinc;        // First frequncy
  2072.  
  2073.         num = chan[i].pinc;                   // calculate second frequency
  2074.         for(j = 0; j < e2; j++) num *= UP_SEMITONE;
  2075.         chan[i].data2  = (WORD)num;
  2076.  
  2077.         num = chan[i].pinc;                   // calculate third frequncy
  2078.         for(j = 0; j < e3; j++) num *= UP_SEMITONE;
  2079.         chan[i].data3  = (WORD)num;
  2080.         chan[i].count = 0;
  2081.         break;
  2082.       case 1:                              // Slide up.
  2083.         chan[i].porta = e2*16 + e3;          // Calculate slide rate
  2084.         break;
  2085.       case 2:                              // slide down
  2086.         chan[i].porta = e2*16 + e3;          // calculate slide rate
  2087.         break;
  2088.       case 3:                              // Slide to note
  2089.         if(e2 || e3) chan[i].porta = e2*16 + e3;
  2090.         if(period) chan[i].period2 = period;
  2091.         break;
  2092.       case 4:                              // Vibrato (My implementation
  2093.                                            // Of this command assumes that
  2094.                                            // The wave form is a triggered
  2095.                                            // Sin wave.   There are other
  2096.                                            // forms defined , but they are
  2097.                                            // use very rarely and I dont't
  2098.                                            // feel like coding them in.
  2099.  
  2100.                                              // These numbers will be used
  2101.                                              // to calculate the waveform.
  2102.         if(e2) chan[i].vibperiod = e2* mod_ticksperdivision;
  2103.         if(e3) chan[i].vibdepth = ((e3/16.0) * 0.0595 ) * chan[i].period;
  2104.         break;
  2105.       case 5:                              // Continue Slide to Note + Volume Slide
  2106.       case 6:                              // Continue Vibrato + volume slide
  2107.                                              // For both of these commands,
  2108.                                              // We just need to keep track
  2109.                                              // of the volume slide rate
  2110.         if((e2 > 0 && e3 > 0) || e3 == 0) chan[i].vslide = e2;
  2111.         else chan[i].vslide = -e3;
  2112.                                              // If the period is specified,
  2113.                                              // Then the volume needs to be
  2114.                                              // reset.
  2115.         if(period)chan[i].volume = mod_data->volume[chan[i].sample_number-1];
  2116.         break;
  2117.       case 7:                              // Tremolo (My implementation
  2118.                                            // Of this command assumes that
  2119.                                            // The wave form is a triggered
  2120.                                            // Sin wave.   There are other
  2121.                                            // forms defined , but they are
  2122.                                            // use very rarely and I dont't
  2123.                                            // feel like coding them in.
  2124.  
  2125.                                              // These values will be used to
  2126.                                              // claculate the wave form
  2127.         if(e2) chan[i].vibperiod = e2* mod_ticksperdivision;
  2128.         if(e3) chan[i].vibdepth = e3;
  2129.         chan[i].volume2 = chan[i].volume;
  2130.         break;
  2131.       case 8:                              // UNUSED
  2132.         break;
  2133.       case 9:                              // Set new sample offset
  2134.         mod_data->offset[chan[i].sample_number-1] = (e2*4096+e3*256)*2;
  2135.         break;
  2136.       case 10:                             // Volume slide
  2137.                                              // Calculate slide rate
  2138.         if((e2 > 0 && e3 > 0) || e3 == 0) chan[i].vslide = e2;
  2139.         else chan[i].vslide = -e3;
  2140.         if(period)chan[i].volume = mod_data->volume[chan[i].sample_number-1];
  2141.         break;
  2142.       case 11:                             // Table position jump
  2143.         mod_tablepos = e2*16+e3;
  2144.         position_jump = TRUE;
  2145.         break;
  2146.       case 12:                             // Set Volume
  2147.         chan[i].volume = e2*16+e3;
  2148.         break;
  2149.       case 13:                             // Pattern Break
  2150.         pattern_break = TRUE;                // We'll do the break later.
  2151.         break;
  2152.       case 14:
  2153.         switch(e2) {
  2154.           case 0:                          // Set filter.  I just ignore this
  2155.                                           // since it is a hardware option
  2156.             break;
  2157.           case 1:                          // Fineslide up
  2158.                                              // Recalculate frequency counter
  2159.             chan[i].period -= e3;
  2160.             rate = 7093789.2/(2* chan[i].period);
  2161.             chan[i].pinc = (rate*256.0)/sample_rate;
  2162.             break;
  2163.           case 2:                          // Fineslide down
  2164.                                              // Recalculate frequncy counter
  2165.             chan[i].period += e3;
  2166.             rate = 7093789.2/(2* chan[i].period);
  2167.             chan[i].pinc = (rate*256.0)/sample_rate;
  2168.             break;
  2169.           case 3:                          // Glissando on/off
  2170.                                            // If this is on, slide-to-note
  2171.                                            // functions should slide by
  2172.                                            // semitones rather than smooth
  2173.                                            // slides.  This is rarely used.
  2174.             mod_glissando = e3;
  2175.             break;
  2176.           case 4:                          // Vibrato waveform. This is rarely
  2177.                                            // used, so for now, the code is
  2178.                                            // locked in to use the default
  2179.                                            // waveform: 0  (a triggered sin
  2180.                                            // wave)
  2181.             break;
  2182.           case 5:                          // Set sample finetune value
  2183.             k = e3;
  2184.             if (k > 7) k -= 16;
  2185.             mod_data->finetune[chan[i].sample_number-1] =  k;
  2186.             break;
  2187.           case 6:                         // Loop Pattern
  2188.                                              // mod_loopcount is a global
  2189.                                              // used to keep track of the loop.
  2190.             if(mod_loopcount == -1) {
  2191.               if(!e3) mod_loopspot = mod_pattern;
  2192.               else {
  2193.                 if(!mod_loopspot) mod_loopspot =
  2194.                   mod_data->pattern_data[mod_data->ptable[mod_tablepos]];
  2195.                 mod_loopcount = e3;
  2196.                 loop = TRUE;
  2197.               }
  2198.             }
  2199.             else if(e3){
  2200.               if(!mod_loopcount) mod_loopspot = NULL;
  2201.               else loop = TRUE;
  2202.               mod_loopcount--;
  2203.             }
  2204.             break;
  2205.           case 7:                          // Termolo waveform.  (see case #4)
  2206.             break;
  2207.           case 8:                          // UNUSED
  2208.             break;
  2209.           case 9:                         // Retrigger sample
  2210.             chan[i].retrigger = e3;          // Set the retrigger signal used
  2211.                                              // in dotick().
  2212.             break;
  2213.           case 10:                        // Fineslide volume up
  2214.             chan[i].volume += e3;
  2215.             if(chan[i].volume > 64) chan[i].volume = 64;
  2216.             break;
  2217.           case 11:                        // Fineslide volume down
  2218.             chan[i].volume -= e3;
  2219.             if(chan[i].volume < 0) chan[i].volume = 0;
  2220.             break;
  2221.           case 12:                        // Cut Sample
  2222.             chan[i].cut = e3;                // Set cut signal for dotick()
  2223.             break;
  2224.           case 13:                        // Delay sample
  2225.             chan[i].data4 = e3;              // Set counter for dotick()
  2226.             chan[i].data3 = chan[i].volume;
  2227.             chan[i].volume = 0;              // Turn off volume
  2228.             break;
  2229.           case 14:                        // Pattern Delay
  2230.             mod_patterndelay = e3;
  2231.             break;
  2232.           case 15:                        // Invert Loop.  THis is too much
  2233.                                           // of a headache to worry about
  2234.                                           // right now. Sorry.
  2235.             break;
  2236.           default:                        // Shouldn't ever get here
  2237.             break;
  2238.         }
  2239.         break;
  2240.       case 15:                            // Set Speed.
  2241.                                              // There are two possible actions
  2242.                                              // with this command:  change
  2243.                                              // ticks per beat, or change
  2244.                                              // beats per minute.  Right
  2245.                                              // now, only the ticks per beat
  2246.                                              // have been implemented.
  2247.         j = e2*16+e3;
  2248.         if(j <= 32) {
  2249.           if(!j) j = 1;
  2250.           mod_ticksperdivision = j;
  2251.         }
  2252.         break;
  2253.       default:                            // shouldn't happen.
  2254.         break;
  2255.     }
  2256.     mod_pattern += 4;                     // Advance to next channel
  2257.   }
  2258.  
  2259.   if(loop) {                              // Loop?  Jump back to placeholder!
  2260.     mod_pattern = mod_loopspot;
  2261.   }
  2262.   else if(pattern_break) {                // Pat. break?  Jump to next pattern!
  2263.     mod_tablepos++;
  2264.     if(mod_tablepos == mod_data->num_positions) mod_on = FALSE;
  2265.     else {
  2266.       mod_pattern = mod_data->pattern_data[mod_data->ptable[mod_tablepos]];
  2267.       mod_pstop = mod_pattern+1024;
  2268.     }
  2269.   }
  2270.   else if(position_jump) {                // Position jump?  Go to specified
  2271.                                           // Table.
  2272.     if(mod_tablepos == mod_data->num_positions) mod_on = FALSE;
  2273.     else {
  2274.       mod_pattern = mod_data->pattern_data[mod_data->ptable[mod_tablepos]];
  2275.       mod_pstop = mod_pattern+1024;
  2276.     }
  2277.   }
  2278. }
  2279.  
  2280.  
  2281. /**************************************************************************
  2282.   MidiPlayer()
  2283.  
  2284.   DESCRIPTION: Routine for playing midi files.  THis is designed to be
  2285.                called from a timer interrupt.  To use, set these values
  2286.                in this order:
  2287.  
  2288.                    midi_data    (must point to a filled MIDI structure.)
  2289.                   midi_reset = TRUE;
  2290.                   midi_on = TRUE;
  2291.  
  2292.                The interrupt should pick up from there.
  2293.  
  2294.                It is easy to add functionality to this routine.  I've
  2295.                already included code to flag a wide variety of MIDI
  2296.                events, so all you have to do is add your own code under
  2297.                the point an event is flagged.  I've left a bunch of
  2298.                commented print statements in to help make the code
  2299.                more readable and provide cues for accessing the data.
  2300.  
  2301.  
  2302.                ***  WARNING  ***
  2303.  
  2304.                If you add your own code here, make sure that it doesn't
  2305.                take more than a few milliseconds to execute.  If
  2306.                MidiPlayer() is called again by the interrupt before your
  2307.                code is done, your whole program will probably crash.
  2308.  
  2309. **************************************************************************/
  2310. void MidiPlayer(void)
  2311. {
  2312.   static VOICE v[9];                    // Nine FM voices
  2313.   VOICE vh[9];                          // waiting list
  2314.   short vhold = 0,spot;
  2315.   static short i,j,live_tracks,vidx;
  2316.   static short divisions = 96,ms_per_div=5000;
  2317.   static BYTE event,ev,ch,b1,b2,etype,track_on[16];
  2318.   static last_ev[16];
  2319.   static WORD trkloc[16];
  2320.   static int itmr,l2,length;
  2321.   static float tmr[16];
  2322.   static char tdata[256];
  2323.  
  2324.   if(!midi_data) {                      // must have data to play!
  2325.     midi_on = FALSE;
  2326.     return;
  2327.   }
  2328.   if(midi_reset) {                       // Reset?  zero track pointers and timers
  2329.     for(i = 0; i < 16; i++ ) {
  2330.       trkloc[i] = 1;                    // no need to read first time offset
  2331.       tmr[i] = 0;                       // all timers start at zero
  2332.       track_on[i] = TRUE;
  2333.       if(i < 9) v[i].active = 0;        // unreserve all voices
  2334.       last_ev[i] = 0x80;                // set last event to note off
  2335.     }
  2336.     midi_reset = 0;                     // clear midi reset flag
  2337.     live_tracks = midi_data->num_tracks;// set number of active tracks so
  2338.                                         // we know when to stop.
  2339.     divisions = midi_data->divisions;   // ticks per quarter note
  2340.     if(divisions < 0) divisions = -divisions;  // some midi files have
  2341.                                                // negative division values
  2342.   }
  2343.  
  2344.   if(!midi_on) return;                   // logical switch for midi on/off
  2345.  
  2346.  
  2347.   for(i = 0 ; i < midi_data->num_tracks; i++) {  // loop over tracks
  2348.     while(tmr[i] <= 0) {                // Process while timer is 0;
  2349.       event = *(TD);                    // get next event (TD is a macro)
  2350.       trkloc[i]++;                      // advance track location pointer
  2351.  
  2352.       if(event == 0xFF) {                 // META event?
  2353.         etype = *(TD);
  2354.         trkloc[i] ++;
  2355.                                         // read length of meta event
  2356.         spot = ReadVarLen(TD,&length);
  2357.         trkloc[i] += spot;
  2358.                                         // grab any text data for text events
  2359.         for(j = 0; j < length; j++) tdata[j] = *(TD + j);
  2360.         tdata[j] = 0;
  2361.  
  2362.  
  2363.         switch(etype) {
  2364.           case 0x00:
  2365.             j = *(TD)*256 + *(TD+1);
  2366.             //printf("[%d] SEQUENCE NUMBER (%d)\n",i,j);
  2367.             break;
  2368.           case 0x01:
  2369.             //printf("[%d] TEXT EVENT (%s)\n",i,tdata);
  2370.             break;
  2371.           case 0x02:
  2372.             //printf("[%d] COPYWRITE EVENT (%s)\n",i,tdata);
  2373.             break;
  2374.           case 0x03:
  2375.             //printf("[%d] TRACK NAME EVENT (%s)\n",i,tdata);
  2376.             break;
  2377.           case 0x04:
  2378.             //printf("[%d] INSTRUMENT NAME EVENT (%s)\n",i,tdata);
  2379.             break;
  2380.           case 0x05:
  2381.             //printf("[%d] LYRIC EVENT (%s)\n",i,tdata);
  2382.             break;
  2383.           case 0x06:
  2384.             //printf("[%d] MARKER EVENT (%s)\n",i,tdata);
  2385.             break;
  2386.           case 0x07:
  2387.             //printf("[%d] CUE EVENT (%s)\n",i,tdata);
  2388.             break;
  2389.            case 0x2f:                   // End of track
  2390.             //printf("[%d] END OF TRACK\n",i);
  2391.             tmr[i] = MAXFLOAT;               // set timer to highest value
  2392.             track_on[i] = FALSE;       // turn off track
  2393.             live_tracks--;             // decrement track counter
  2394.             if(live_tracks == 0) {     // last track?  Turn off midi!
  2395.               midi_on = FALSE;
  2396.               midi_reset = TRUE;       // Make sure we start over
  2397.               return;
  2398.             }
  2399.             break;
  2400.           case 0x51:                   // TEMPO event (microsecs per 1/4 note)
  2401.             l2 = *(TD) * 0x10000L + *(TD+1) * 0x100 + *(TD+2);
  2402.             //printf("[%d] TEMPO EVENT (%ld)\n",i,l2);
  2403.         ms_per_div = (short)(l2/divisions);
  2404.                                        // Convert number to a counter used
  2405.                                        // by an 183 Hhz interrupt.
  2406.             midi_callfreq = ms_per_div/5454.0;
  2407.             break;
  2408.           case 0x58:
  2409.             //printf("[%d] TIME SIG EVENT (%X,%X,%X,%X)\n",i,
  2410.             //        *(TD),*(TD+1),*(TD+2),*(TD+3));
  2411.             break;
  2412.           case 0x59:
  2413.             //printf("[%d] KEY SIG EVENT (%X,%X)\n",i,*(TD),*(TD+1));
  2414.             break;
  2415.           case 0x7F:
  2416.             //printf("[%d] SEQUENCER DATA EVENT\n",i);
  2417.             break;
  2418.           default:
  2419.             //printf("[%d] *** undefined event *** (%X,type: %X,length %ld)\n",i,event,etype,length);
  2420.             break;
  2421.         }
  2422.         trkloc[i] += (WORD)length;
  2423.       }
  2424.       else if(event == 0xF0 || event == 0xF7) { // sysex event
  2425.         trkloc[i] += ReadVarLen(TD,&length);
  2426.         //printf("Sysex type 1 [length: %ld]\n",length);
  2427.         trkloc[i] += (WORD)length;
  2428.       }
  2429.       else {                           // PROCESS MIDI EVENTS
  2430.  
  2431.         if(!(event & 0x80)) {          // top bit Not set? Running status!
  2432.  
  2433.           b1 = event;                  // b1 = note   (usually)
  2434.           b2 = *(TD + 1);              // b2 = volume? (usually)
  2435.  
  2436.  
  2437.           event = last_ev[i];          // use last event
  2438.           //printf("Running status >>");
  2439.           //for(j = 0; j < 9; j++) printf("%d",v[j].active);
  2440.           //printf("\n");
  2441.           trkloc[i] --;                // one less byte for running status.
  2442.  
  2443.           if(midi_mpuout) {
  2444.             ev = event & 0xF0;
  2445.             MPU_Write(event);
  2446.             MPU_Write(b1);
  2447.             if(ev != 0xC0 && ev != 0xD0) MPU_Write(b2);
  2448.           }
  2449.         }
  2450.         else {                         // Else it was a regular event
  2451.           ev = event & 0xF0;
  2452.           event = ev + midi_patchmap[ch];
  2453.  
  2454.           last_ev[i] = event;          // set to last event
  2455.           b1 = *(TD);                   // get next two bytes
  2456.           b2 = *(TD+1);
  2457.           if(midi_mpuout) {
  2458.             MPU_Write(event);
  2459.             MPU_Write(b1);
  2460.             if(ev != 0xC0 && ev != 0xD0) MPU_Write(b2);
  2461.           }
  2462.         }
  2463.         ev = event & 0xF0;             // strip lower four bits
  2464.         ch = event & 0x0f;             // channel
  2465.         vidx = getvoice(v,i,ch,b1);    // Get a voice index
  2466.  
  2467.         switch(ev) {
  2468.           case 0x80:                   // Note off
  2469.             //printf("[%d] Note off (%d,%d)\n",i,b1,b2);
  2470.             trkloc[i] += 2;
  2471.             if(vidx > -1) {            // If a matching voice was found,
  2472.                                        // kill it.
  2473.               FM_KeyOff(vidx);
  2474.               FM_SetVol(vidx,0);
  2475.               v[vidx].active = FALSE;
  2476.             }
  2477.             break;
  2478.           case 0x90:                   // Note On
  2479.             //printf("[%d] Note on (%X,%d,%d)\n",i,event,b1,b2);
  2480.             //printf("%X",ch);
  2481.             trkloc[i] += 2;
  2482.             if(vidx > -1) {            // Voice found?
  2483.               if(v[vidx].active) {     // already active? Turn it off.
  2484.                 v[vidx].active = FALSE;
  2485.                 FM_KeyOff(vidx);
  2486.                 FM_SetVol(vidx,0);
  2487.               }
  2488.               else if(midi_fmout){      // Wasn't active?  Turn it on.
  2489.                 v[vidx].owner_track = i;
  2490.                 v[vidx].owner_channel = ch;
  2491.                 v[vidx].note = b1;
  2492.                 v[vidx].volume = b2;
  2493.                 v[vidx].active = TRUE;
  2494.                 FM_SetNote(vidx,b1);
  2495.                 FM_SetVol(vidx,music_volume);
  2496.                 FM_KeyOn(vidx);
  2497.               }
  2498.             }
  2499.             else {                     // There might be space later
  2500.                                        // store our note
  2501.               vh[vhold].owner_track = i;
  2502.               vh[vhold].owner_channel = ch;
  2503.               vh[vhold].note = b1;
  2504.               vh[vhold].volume = b2;
  2505.               vhold ++;
  2506.               if(vhold >8) vhold = 8;  //  Only nine hold notes considered
  2507.             }
  2508.             break;
  2509.           case 0xA0:                   // Key pressure
  2510.             //printf("[%d] Note presure (%d,%d)\n",i,b1,b2);
  2511.             trkloc[i] += 2;
  2512.             break;
  2513.           case 0xB0:                   // Control CHange
  2514.             //printf("[%d] Control Change (%d,%d)\n",i,b1,b2);
  2515.             trkloc[i] += 2;
  2516.             break;
  2517.           case 0xC0:                   // Program change
  2518.             //printf("[%d] Program change (%d)\n",i,b1);
  2519.             trkloc[i] += 1;
  2520.             if(midi_mpuout) {
  2521.               MPU_Write(event);
  2522.               MPU_Write(b1);
  2523.             }
  2524.             break;
  2525.           case 0xD0:                   // Channel Pressure
  2526.             //printf("[%d] Channel Pressure (%d,%d)\n",i,b1);
  2527.             trkloc[i] += 1;
  2528.             break;
  2529.           case 0xE0:                   // Pitch wheel change
  2530.             //printf("[%d] Pitch change (%d,%d)\n",i,b1,b2);
  2531.             trkloc[i] += 2;
  2532.             if(midi_mpuout) {
  2533.               MPU_Write(event);
  2534.               MPU_Write(b1);
  2535.               MPU_Write(b2);
  2536.             }
  2537.             break;
  2538.           default:                     // Uh-OH
  2539.             //printf("MIDI ERROR (F0 midi command)\n");
  2540.             midi_on = FALSE;
  2541.             return;
  2542.         }
  2543.       }
  2544.                                          // read next time offset
  2545.       if(track_on[i]) {
  2546.         trkloc[i] += ReadVarLen(TD,&itmr);
  2547.         tmr[i] += itmr;
  2548.         //printf(" T: %ld\n",tmr[i]);
  2549.       }
  2550.     }
  2551.     tmr[i]-= 1.0 * midi_tempoadjust;                           // decrement timer
  2552.   }
  2553.  
  2554.                                         // Since there is a limited number
  2555.                                         // of FM voices, some notes do
  2556.                                         // not get voiced.  This next
  2557.                                         // section takes a list of
  2558.                                         // unallocated notes and tries
  2559.                                         // to find a spot for them.
  2560.   while(vhold) {
  2561.     vhold--;                            // go to next note
  2562.     for(i = 0; i < 9; i++) {            // loop through FM voices
  2563.       if(!v[i].active) {                // found empty one? set the note!
  2564.         v[i].owner_track = vh[vhold].owner_track;
  2565.         v[i].owner_channel = vh[vhold].owner_channel;
  2566.         v[i].note = vh[vhold].note;
  2567.         v[i].volume = vh[vhold].volume;
  2568.         v[i].active = TRUE;
  2569.         FM_SetNote(i,b1);
  2570.         FM_SetVol(i,music_volume);
  2571.         FM_KeyOn(i);
  2572.         break;
  2573.       }
  2574.     }
  2575.     if(i == 9) vhold = 0;               // List full? forget about other notes
  2576.   }
  2577.  
  2578.  
  2579. }
  2580.  
  2581. /**************************************************************************
  2582.   ReadMidi(char *filename, MIDI *mdata, char *errstring)
  2583.  
  2584.   DESCRIPTION: Reads a midi file and stores it to a MIDI data structure
  2585.  
  2586.   INPUTS:
  2587.  
  2588.     filename    Pointer to full midi filename
  2589.     midipoint    Indirect pointer to empty midi pointer
  2590.     errstring    Pointer to a pre-allocated string.
  2591.  
  2592.   Outputs:
  2593.     returns 0 if successful.
  2594.     On error, it returns a number and fills errstring with the
  2595.       error message.
  2596.  
  2597. **************************************************************************/
  2598. short ReadMidi(char *filename, MIDI **midipoint, char *errstring)
  2599. {
  2600.   short i;
  2601.   FILE *input;
  2602.   char sdata[256];
  2603.   int lidata;
  2604.   short idata;
  2605.   DWORD lread;
  2606.   MIDI *mdata;
  2607.  
  2608.   input = fopen(filename,"rb");            // open a midi file
  2609.   if(!input) {
  2610.     sprintf(errstring,"cannot open %s",filename);
  2611.     return(1);
  2612.   }
  2613.                                            // Read the header
  2614.  
  2615.   fread(sdata,1,4,input);                  // midi id there?
  2616.   sdata[4] = 0;
  2617.   if(strcmp(sdata,"MThd")) {
  2618.     sprintf(errstring,"Not a  midi file.");
  2619.     fclose(input);
  2620.     return(2);
  2621.   }
  2622.   // printf("Chunk type: %s\n",sdata);
  2623.  
  2624.   lidata = ReadLong(input);                // length of remaining header chunk?
  2625.   // printf("Chunk length: %ld\n",lidata);
  2626.   if(lidata > 250) {
  2627.     sprintf(errstring,"Header chunk has a weird length");
  2628.     exit(0);
  2629.   }
  2630.  
  2631.   mdata = (MIDI *)malloc(sizeof(MIDI));    // make room for music!
  2632.   if(!mdata) {
  2633.     sprintf(errstring,"Out of memory.");
  2634.     fclose(input);
  2635.     return(3);
  2636.   }
  2637.   *midipoint = mdata;                       // Assign our pointer
  2638.  
  2639.   idata = ReadShort(input);                // Format
  2640.   //printf("Format: %d\n",idata);
  2641.   if(idata != 0 && idata != 1) {
  2642.     sprintf(errstring,"Unrecognized MIDI format");
  2643.     fclose(input);
  2644.     return(4);
  2645.   }
  2646.  
  2647.   mdata->format = idata;
  2648.  
  2649.   idata = ReadShort(input);                // number of tracks
  2650.   //printf("# of Tracks: %d\n",idata);
  2651.   if(idata < 1 || idata > 16) {
  2652.     sprintf(errstring,"Bad number of tracks [%d]",idata);
  2653.     fclose(input);
  2654.     return(5);
  2655.   }
  2656.   mdata->num_tracks = idata;
  2657.  
  2658.   idata = ReadShort(input);                // division number (tempo)
  2659.   //printf("1/4 note division: %d\n",idata);
  2660.   mdata->divisions = abs(idata);
  2661.  
  2662.                                            // Read individual track data
  2663.   for(i = 0; i < mdata->num_tracks; i++) {
  2664.     fread(sdata,1,4,input);                // midi track id there?
  2665.     sdata[4] = 0;
  2666.     if(strcmp(sdata,"MTrk")) {
  2667.       sprintf(errstring,"Error reading track #%d",i);
  2668.       fclose(input);
  2669.       return(6);
  2670.     }
  2671.     //printf("Chunk type: %s\n",sdata);
  2672.  
  2673.     lidata = ReadLong(input);              // length of remaining track chunk?
  2674.     //printf("Chunk length: %ld\n",lidata);
  2675.  
  2676.                                            // Allocate space for track
  2677.     mdata->track[i] = (BYTE *)malloc(lidata);
  2678.     if(!mdata->track[i]) {
  2679.       sprintf(errstring,"Out of memory.");
  2680.       fclose(input);
  2681.       return(3);
  2682.     }
  2683.                                            // read in entire track
  2684.     lread = fread(mdata->track[i],1,(size_t)lidata,input);
  2685.     if(lread < lidata) {
  2686.       sprintf(errstring,"Premature end of midi file [track %d]",i);
  2687.       fclose(input);
  2688.       return(7);
  2689.     }
  2690.   }
  2691.  
  2692.   fclose(input);
  2693.   return 0;
  2694. }
  2695.  
  2696.  
  2697. /**************************************************************************
  2698.    short ReadVarLen(char *data,int *value)
  2699.  
  2700.   DESCRIPTION:  Reads a variable length long interger from data string.
  2701.                 This functionis used by ReadMidi() to grab special numbers
  2702.                 from MIDI data files.
  2703.  
  2704. **************************************************************************/
  2705. short ReadVarLen(BYTE *data,int *value)
  2706. {
  2707.   short i=0;
  2708.   BYTE c;
  2709.  
  2710.   if ((*value = *(data + i)) & 0x80) {
  2711.     *value &= 0x7f;
  2712.     do {
  2713.       i++;
  2714.       *value = (*value << 7) + ((c = *(data +i)) & 0x7f);
  2715.     } while (c & 0x80);
  2716.   }
  2717.   return(i+1);                       // return number of bytes read
  2718. }
  2719.  
  2720.  
  2721. /**************************************************************************
  2722.   int ReadShort(FILE *inflile)
  2723.  
  2724.   DESCRIPTION:  Reads a short interger from a file
  2725.  
  2726. **************************************************************************/
  2727. short ReadShort(FILE *infile)
  2728. {
  2729.   return (fgetc(infile) << 8) | fgetc(infile);
  2730. }
  2731.  
  2732. /**************************************************************************
  2733.   int ReadLong(FILE *inflile)
  2734.  
  2735.   DESCRIPTION:  Reads a long interger from a file
  2736.  
  2737. **************************************************************************/
  2738. int ReadLong(FILE *infile)
  2739. {
  2740.   short i;
  2741.   int num = 0;
  2742.  
  2743.   num = (unsigned char)fgetc(infile);
  2744.  
  2745.   for(i = 0; i < 3; i++) {
  2746.     num = (num << 8) | (unsigned char)fgetc(infile);
  2747.   }
  2748.  
  2749.   return(num);
  2750. }
  2751.  
  2752.  
  2753. /**************************************************************************
  2754.   void playsound(SAMPLE *data,length)
  2755.  
  2756.   DESCRIPTION: Adds a sound to the play list.  If the playlist is full,
  2757.                all the sounds are scooted over and the new sound is  added
  2758.                as the last item;
  2759.  
  2760. **************************************************************************/
  2761. void playsound(SAMPLE *data,DWORD length)
  2762. {
  2763.   short i;
  2764.  
  2765.   if(sounds_in_queue >= MAXSOUNDS) {       // List full?
  2766.     for(i= 0; i <sounds_in_queue; i++) {   // Scoot all the sounds down and
  2767.                                            // discard sound 0.
  2768.       sounddata[i] = sounddata[i+1];
  2769.       soundpos[i] = soundpos[i+1];
  2770.     }
  2771.     sounds_in_queue--;
  2772.   }
  2773.  
  2774.  
  2775.   sounddata[sounds_in_queue] = data;       // Add the new sound
  2776.   soundpos[sounds_in_queue] = length-1;
  2777.  
  2778.   sounds_in_queue++;
  2779. }
  2780. /**************************************************************************
  2781.   MOD *loadmod(char *modfilename)
  2782.  
  2783.   DESCRIPTION:  Loads a Module file (Noise,Sound, or Protracker)
  2784.  
  2785.  
  2786. **************************************************************************/
  2787. MOD *loadmod(char *modfilename)
  2788. {
  2789.   short i,j,ft;
  2790.   FILE *input;
  2791.   MOD *m;
  2792.   char signature[5];
  2793.   short samples = 15;
  2794.  
  2795.   m = (MOD *)malloc(sizeof(MOD));         // Allocate the skeleton MOD struct
  2796.   if(!m) {
  2797.     return(NULL);
  2798.   }
  2799.  
  2800.   input = fopen(modfilename,"rb");         // access the file
  2801.   if(!input) {
  2802.     free(m);
  2803.     return(NULL);
  2804.   }
  2805.  
  2806.   fseek(input,1080, SEEK_SET);            // Look for signatures so we
  2807.                                           // can tell of this MOD has 15
  2808.                                           // Or 31 samples.
  2809.   fread(signature,1,4,input);
  2810.   signature[4] = 0;
  2811.   if(!strcmp(signature,"M.K.")) samples = 31;
  2812.   else if(!strcmp(signature,"M!K!")) samples = 31;
  2813.   else if(!strcmp(signature,"FLT4")) samples = 31;
  2814.  
  2815.   rewind(input);                          // Go back to the start.
  2816.  
  2817.   fread(m->title,1,20,input);              // read the module title
  2818.  
  2819.   m->num_samples = 0;
  2820.  
  2821.   for(i = 0; i < samples; i++) {          // read the sample headers
  2822.     fread(m->sample_name[i],1,22,input);  // name
  2823.                                           // length (convert words to bytes)
  2824.     m->slength[i] = (fgetc(input) * 256+ fgetc(input))*2;
  2825.     ft = fgetc(input)&0x0f;                // finetune
  2826.     if(ft>7) ft -=16;                     // Convert to a signed value
  2827.     m->finetune[i] = ft;
  2828.  
  2829.     m->volume[i] = fgetc(input);          // Sample volume
  2830.                                           // repeat offset (words -> bytes)
  2831.     m->offset[i] = (fgetc(input) * 256 + fgetc(input))*2;
  2832.                                           // repeat length (words -> bytes)
  2833.     m->repeat[i] = (fgetc(input) * 256 + fgetc(input))*2;
  2834.     if(m->repeat[i] == 2) m->repeat[i] = 0;
  2835.  
  2836.                                           // Sometimes the repeat length
  2837.                                           // and offset are not set properly,
  2838.                                           // so we have to do a little
  2839.                                           // patching here.
  2840.     if(m->offset[i] + m->repeat[i] > m->slength[i] ) {
  2841.       if(m->repeat[i] > m->slength[i]) {
  2842.         m->repeat[i] = m->slength[i];
  2843.         m->offset[i] = 0;
  2844.       }
  2845.       else {
  2846.         m->offset[i] -= (m->repeat[i] + m->offset[i] - m->slength[i]);
  2847.       }
  2848.     }
  2849.  
  2850.     if(m->slength) m->num_samples++;      // Keep track of the number of real smaples
  2851.   }
  2852.  
  2853.   m->num_positions = fgetc(input);        // number of patterns to play
  2854.   fgetc(input);                           // unused byte
  2855.   fread(m->ptable,1,128,input);           // read pattern table
  2856.  
  2857.   if(samples == 31) {
  2858.     fread(m->sig,1,4,input);              // read module signature
  2859.     m->sig[4] = 0;
  2860.   }
  2861.   else strcpy(m->sig,"NONE");
  2862.  
  2863.   m->maxpattern = 0;
  2864.  
  2865.   for(i = 0; i < m->num_positions; i++) { // Find number of unique patterns
  2866.     if(m->ptable[i] > m->maxpattern) m->maxpattern = m->ptable[i];
  2867.   }
  2868.  
  2869.   for(i=0;i<128;i++) m->pattern_data[i]=NULL;  // Reset pattern buffer pointers
  2870.  
  2871.   for(i = 0; i <= m->maxpattern; i++) {   // read in 1024-byte patterns
  2872.     m->pattern_data[i] = (BYTE *)malloc(1024);
  2873.  
  2874.     if(!m->pattern_data[i]) {             // Did we get the memory?
  2875.                                           // If not, free what we have
  2876.                                           // and go home.
  2877.       for(j = 0; j < i; j++) free(m->pattern_data[j]);
  2878.       free(m);
  2879.       return(NULL);
  2880.     }
  2881.     fread(m->pattern_data[i],1,1024,input);  // Read in the pattern
  2882.   }
  2883.                                           // Reset sample data pointers
  2884.   for(i = 0; i < 32; i++) m->sdata[i] = NULL;
  2885.  
  2886.   for(i = 0; i <samples; i++) {           // Read in the sample data
  2887.     m->sdata[i] = NULL;                   // Reset sample
  2888.     if(!m->slength[i]) continue;          // Continue if nothing to read
  2889.  
  2890.     m->sdata[i] = (SAMPLE *)malloc(m->slength[i]+1);
  2891.  
  2892.     if(!m->sdata[i]) {                    // Did we get the memory?
  2893.                                           // If not, free what we have
  2894.                                           // and go home.
  2895.       for(j = 0; j <= m->maxpattern; j++) free(m->pattern_data[j]);
  2896.       for(j = 0; j < i; j++) free(m->sdata[j]);
  2897.       free(m);
  2898.       return(NULL);
  2899.     }
  2900.                                           // Read in the sample
  2901.     fread(m->sdata[i],1,m->slength[i],input);
  2902.  
  2903.   }
  2904.   fclose(input);                          // All done!
  2905.  
  2906.  
  2907.   return(m);                              // Give the new Module back to
  2908.                                           // the caller.
  2909.  
  2910. }
  2911.  
  2912.  
  2913.  
  2914. /*********************************************************************
  2915.   SAMPLE *loadwave(char *wavefile,unsigned int *length)
  2916.  
  2917.   DESCRIPTION:  Loads a wave files  (mono, 8bit)
  2918.  
  2919.   INTPUTS:
  2920.  
  2921.     wavefile  filename of wave file
  2922.     length    pointer to length interger
  2923.  
  2924.   RETURNS:
  2925.     pointer to data
  2926.  
  2927. **********************************************************************/
  2928. SAMPLE *loadwave(char *wavefile,unsigned int *length)
  2929. {
  2930.   short i;
  2931.   SAMPLE  *data;
  2932.   BYTE dummydata[255];
  2933.   FILE *input;
  2934.   DWORD rlen,flen;
  2935.   WORD s_per_sec,b_per_sec,num_channels,tag;
  2936.   char riffid[5],waveid[5],fmtid[5],dataid[5];
  2937.  
  2938.   input = fopen(wavefile,"rb");
  2939.   if(!input) {                              // If unsuccesful...
  2940.     *length = 1;                             // set short length to prevent
  2941.                         // mistakes later.
  2942.     return(NULL);                           // REturn a null pointer
  2943.   }
  2944.                                             // Get WAVE header data
  2945.  
  2946.   fread(riffid,1,4,input);                  // wave files staqrt with "Riff"
  2947.   riffid[4] = 0;
  2948.   fread(&rlen,1,4,input);                   // File size
  2949.   fread(waveid,1,4,input);                  // Wave id string  ("Wave")
  2950.   waveid[4] = 0;
  2951.   if(strcmp(waveid,"WAVE")) {               // is it a wave file?
  2952.     fclose(input);
  2953.     return(NULL);
  2954.   }
  2955.  
  2956.   fread(fmtid,1,4,input);                   // Format id string ("fmt ")
  2957.   fmtid[4] = 0;
  2958.   fread(&flen,1,4,input);                   // offset to data
  2959.   if(flen > 240) flen = 240;                // Just a precaution so that
  2960.                                             // We do not overload dummydata
  2961.  
  2962.   fread(&tag,1,2,input);                    // tag
  2963.   fread(&num_channels,1,2,input);           // number of channels
  2964.   fread(&s_per_sec,1,2,input);              // sample rate (hz)
  2965.   fread(&b_per_sec,1,2,input);              // bytes per seconf rate
  2966.   fread(dummydata,1,(size_t)flen-8,input);          // Skip ahead
  2967.   fread(dataid,1,4,input);                  // Dataid string
  2968.   dataid[4] = 0;
  2969.   fread(length,1,4,input);                  // length of data
  2970.  
  2971.   data = (SAMPLE *)malloc(*length+1);    // allocate memory for data
  2972.   if(!data) {                                // oops.  Not enough mem!
  2973.     fclose(input);
  2974.     return(NULL);
  2975.   }
  2976.  
  2977.   fread(data,1,(size_t)*length,input);              // read the data
  2978.  
  2979.   for(i = 0; i < *length; i++) {            // convert to signed format
  2980.     *(data + i) = ((BYTE)*(data + i))-128;
  2981.   }
  2982.  
  2983.   fclose(input);                            // Wrap it up
  2984.   return(data);
  2985. }
  2986.  
  2987.  
  2988. /**************************************************************************
  2989.   void load_instruments(char *filename,BYTE inst[128][11])
  2990.  
  2991.   DESCRIPTION:  Loads instrument defs from a file (128 total)
  2992.  
  2993.     File format: 11 hex values followed by a name.  eg:
  2994.  
  2995.       30 33 40 00 E1 E2 87 63 06 01 00 "Electric Piano 2"
  2996.       33 34 00 00 92 C3 C3 B3 02 01 00 "Harpsichord"
  2997.       32 32 00 00 92 C3 C3 B3 02 01 00 "Clavichord"
  2998.       .
  2999.       .
  3000.       .
  3001.  
  3002.     (The text at the end is ignored.)
  3003.  
  3004.     The hex values are dumped into an 2-D array.  The file can have
  3005.     more or less than 128 defs without harm to this function.
  3006.  
  3007. **************************************************************************/
  3008. short load_instruments(char *filename,BYTE inst[128][11])
  3009. {
  3010.   FILE *input;
  3011.   short i=0,j;
  3012.   char string[255];
  3013.  
  3014.   input = fopen(filename,"r");     // open the file
  3015.   if(!input) return(0);
  3016.                                    // read  it's contents
  3017.   while(fgets(string,255,input) && i < 128) {
  3018.     for(j = 0; j < 11; j++) sscanf(string+j*3,"%X ",&inst[i][j]);
  3019.     i++;
  3020.   }
  3021.                                    // clean up and go home
  3022.   fclose(input);
  3023.   return(i);
  3024. }
  3025.  
  3026.  
  3027.  
  3028. /**************************************************************************
  3029.   void freemidi(MIDI *m)
  3030.  
  3031.   DESCRIPTION: Frees the data allocated for a MIDI structure
  3032.  
  3033. **************************************************************************/
  3034. void freemidi(MIDI *m)
  3035. {
  3036.   short i;
  3037.  
  3038.   for(i = 0; i < m->num_tracks; i++) free(m->track[i]);
  3039.   free(m);
  3040. }
  3041.  
  3042. /**************************************************************************
  3043.   void freemod(MOD *freeme)
  3044.  
  3045.   DESCRIPTION: Frees all the memory associated with a MOD file.
  3046.  
  3047.   BYTE far *pattern_data[128];
  3048.   SAMPLE *sdata[32];
  3049.  
  3050. **************************************************************************/
  3051. void freemod(MOD *freeme)
  3052. {
  3053.   short i;
  3054.  
  3055.   for(i = 0; i <32; i++) {           // Free the samples
  3056.     if(freeme->sdata[i]) free(freeme->sdata[i]);
  3057.   }
  3058.   for(i = 0; i <128; i++) {         // Free the pattern data
  3059.     if(freeme->pattern_data[i]) free(freeme->pattern_data[i]);
  3060.   }
  3061.   free(freeme);
  3062.  
  3063. }
  3064.  
  3065. /**************************************************************************
  3066.   void VarmintVSync(void)
  3067.  
  3068.   DESCRIPTION: This vsync function pays attention to vsyncclock so that we
  3069.                  never miss a vsync.  The vsync can be missed if sb_int
  3070.                 gets called while we are waiting for the retrace.
  3071.  
  3072.                 The variable vsync_toolong should be roughly equalt to
  3073.                 the number of times you expect sb_int to get called between
  3074.                 vertical retraces.  The will be afffected by dma_bufferlen,
  3075.                 sample_rate, and the frequency of the VGA monitor
  3076.  
  3077. **************************************************************************/
  3078. void VarmintVSync(void)
  3079. {
  3080.   while(!(inp(0x3da)&0x08)) {     // Wait for retrace to start
  3081.     if(vsyncclock>vsync_toolong) break;   // Have we waited too long?
  3082.   }
  3083.  
  3084.   while(inp(0x3da)&0x08);          // Wait for retrace to finish
  3085.   vsyncclock = 0;                     // reset the clock
  3086. }
  3087.  
  3088. // This function allocates memory from the low 640K
  3089. // At this point no error checking is done to verify it works
  3090.  
  3091. void *real_malloc(int size,int* handle)
  3092. {
  3093. union REGS dos;
  3094.  
  3095. dos.x.eax=0x100;  //Function in DPMI to allocate REAL MEMORY
  3096. dos.x.ebx=(size+15)>>4; //change it to 16 byte block
  3097.  
  3098. int386(0x31,&dos,&dos);
  3099.    //AX holds Segment
  3100.    //DX holds base selector of allocated block
  3101.  
  3102. if (dos.x.cflag)
  3103.    return(NULL);
  3104.  
  3105. *handle=dos.w.dx;
  3106. return((void*)((dos.x.eax &0xffff)<<4));
  3107.   //Change segement to a protected mode pointer
  3108. }
  3109.  
  3110.  
  3111. // This function frees up memory allocated by the real malloc function
  3112. void real_free(int handle)
  3113. {
  3114. union REGS dos;
  3115. dos.w.ax=0x101;
  3116. dos.w.dx=handle;
  3117. int386(0x31,&dos,&dos);
  3118.  
  3119.  
  3120. }
  3121.  
  3122.